@metamask/snaps-controllers 0.24.1 → 0.26.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/dist/cronjob/CronjobController.d.ts +3 -2
- package/dist/cronjob/CronjobController.js +37 -23
- package/dist/cronjob/CronjobController.js.map +1 -1
- package/dist/fsm.js +1 -1
- package/dist/fsm.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/multichain/MultiChainController.d.ts +3 -1
- package/dist/multichain/MultiChainController.js +8 -8
- package/dist/multichain/MultiChainController.js.map +1 -1
- package/dist/multichain/middleware.d.ts +1 -1
- package/dist/multichain/middleware.js +2 -2
- package/dist/multichain/middleware.js.map +1 -1
- package/dist/services/AbstractExecutionService.d.ts +3 -3
- package/dist/services/AbstractExecutionService.js +13 -12
- package/dist/services/AbstractExecutionService.js.map +1 -1
- package/dist/services/ExecutionService.d.ts +1 -1
- package/dist/services/ExecutionService.js.map +1 -1
- package/dist/services/iframe/IframeExecutionService.js +1 -1
- package/dist/services/iframe/IframeExecutionService.js.map +1 -1
- package/dist/services/iframe/test/server.js +6 -6
- package/dist/services/iframe/test/server.js.map +1 -1
- package/dist/services/node/NodeProcessExecutionService.d.ts +1 -1
- package/dist/services/node/NodeProcessExecutionService.js +2 -2
- package/dist/services/node/NodeProcessExecutionService.js.map +1 -1
- package/dist/services/node/NodeThreadExecutionService.d.ts +2 -2
- package/dist/services/node/NodeThreadExecutionService.js +5 -4
- package/dist/services/node/NodeThreadExecutionService.js.map +1 -1
- package/dist/snaps/SnapController.d.ts +37 -47
- package/dist/snaps/SnapController.js +306 -228
- package/dist/snaps/SnapController.js.map +1 -1
- package/dist/snaps/endowments/cronjob.d.ts +2 -2
- package/dist/snaps/endowments/cronjob.js +3 -3
- package/dist/snaps/endowments/cronjob.js.map +1 -1
- package/dist/snaps/endowments/enum.d.ts +2 -1
- package/dist/snaps/endowments/enum.js +1 -0
- package/dist/snaps/endowments/enum.js.map +1 -1
- package/dist/snaps/endowments/ethereum-provider.d.ts +1 -1
- package/dist/snaps/endowments/ethereum-provider.js +2 -2
- package/dist/snaps/endowments/ethereum-provider.js.map +1 -1
- package/dist/snaps/endowments/index.d.ts +33 -19
- package/dist/snaps/endowments/index.js +16 -4
- package/dist/snaps/endowments/index.js.map +1 -1
- package/dist/snaps/endowments/keyring.d.ts +1 -1
- package/dist/snaps/endowments/keyring.js +2 -2
- package/dist/snaps/endowments/keyring.js.map +1 -1
- package/dist/snaps/endowments/long-running.d.ts +1 -1
- package/dist/snaps/endowments/long-running.js +2 -2
- package/dist/snaps/endowments/long-running.js.map +1 -1
- package/dist/snaps/endowments/network-access.d.ts +1 -1
- package/dist/snaps/endowments/network-access.js +2 -2
- package/dist/snaps/endowments/network-access.js.map +1 -1
- package/dist/snaps/endowments/rpc.d.ts +35 -0
- package/dist/snaps/endowments/rpc.js +91 -0
- package/dist/snaps/endowments/rpc.js.map +1 -0
- package/dist/snaps/endowments/transaction-insight.d.ts +3 -3
- package/dist/snaps/endowments/transaction-insight.js +3 -3
- package/dist/snaps/endowments/transaction-insight.js.map +1 -1
- package/dist/snaps/index.d.ts +0 -1
- package/dist/snaps/index.js +0 -1
- package/dist/snaps/index.js.map +1 -1
- package/dist/snaps/location/http.d.ts +21 -0
- package/dist/snaps/location/http.js +71 -0
- package/dist/snaps/location/http.js.map +1 -0
- package/dist/snaps/location/index.d.ts +4 -0
- package/dist/snaps/{utils → location}/index.js +3 -1
- package/dist/snaps/location/index.js.map +1 -0
- package/dist/snaps/location/local.d.ts +10 -0
- package/dist/snaps/location/local.js +51 -0
- package/dist/snaps/location/local.js.map +1 -0
- package/dist/snaps/location/location.d.ts +32 -0
- package/dist/snaps/location/location.js +33 -0
- package/dist/snaps/location/location.js.map +1 -0
- package/dist/snaps/location/npm.d.ts +33 -0
- package/dist/snaps/location/npm.js +232 -0
- package/dist/snaps/location/npm.js.map +1 -0
- package/dist/utils.d.ts +10 -3
- package/dist/utils.js +17 -1
- package/dist/utils.js.map +1 -1
- package/package.json +25 -20
- package/dist/snaps/utils/index.d.ts +0 -2
- package/dist/snaps/utils/index.js.map +0 -1
- package/dist/snaps/utils/npm.d.ts +0 -14
- package/dist/snaps/utils/npm.js +0 -81
- package/dist/snaps/utils/npm.js.map +0 -1
- package/dist/snaps/utils/stream.d.ts +0 -30
- package/dist/snaps/utils/stream.js +0 -124
- package/dist/snaps/utils/stream.js.map +0 -1
|
@@ -21,25 +21,24 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
21
21
|
}
|
|
22
22
|
return t;
|
|
23
23
|
};
|
|
24
|
-
var
|
|
25
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
26
|
-
};
|
|
27
|
-
var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_environmentEndowmentPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_checkSnapBlockList, _SnapController_maxIdleTime, _SnapController_npmRegistryUrl, _SnapController_getAppKey, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsUnblocked, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_getEncryptionKey, _SnapController_encryptSnapState, _SnapController_decryptSnapState, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_fetchNpmSnap, _SnapController_fetchLocalSnap, _SnapController_processSnapPermissions, _SnapController_getRpcRequestHandler, _SnapController_executeWithTimeout, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange;
|
|
24
|
+
var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_environmentEndowmentPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_checkSnapBlockList, _SnapController_maxIdleTime, _SnapController_npmRegistryUrl, _SnapController_detectSnapLocation, _SnapController_rollbackSnapshots, _SnapController_getAppKey, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsUnblocked, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_getEncryptionKey, _SnapController_encryptSnapState, _SnapController_decryptSnapState, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_fetchSnap, _SnapController_processSnapPermissions, _SnapController_getRpcRequestHandler, _SnapController_executeWithTimeout, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRollbackSnapshot, _SnapController_createRollbackSnapshot, _SnapController_rollbackSnap, _SnapController_rollbackSnaps, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange, _SnapController_isValidUpdate;
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
26
|
exports.SnapController = exports.AppKeyType = exports.SNAP_APPROVAL_UPDATE = exports.SNAP_APPROVAL_INSTALL = exports.controllerName = void 0;
|
|
30
|
-
const
|
|
31
|
-
const
|
|
27
|
+
const base_controller_1 = require("@metamask/base-controller");
|
|
28
|
+
const browser_passworder_1 = require("@metamask/browser-passworder");
|
|
29
|
+
const rpc_methods_1 = require("@metamask/rpc-methods");
|
|
32
30
|
const snaps_utils_1 = require("@metamask/snaps-utils");
|
|
31
|
+
const subject_metadata_controller_1 = require("@metamask/subject-metadata-controller");
|
|
33
32
|
const utils_1 = require("@metamask/utils");
|
|
34
33
|
const fsm_1 = require("@xstate/fsm");
|
|
35
34
|
const eth_rpc_errors_1 = require("eth-rpc-errors");
|
|
36
35
|
const nanoid_1 = require("nanoid");
|
|
37
|
-
const rpc_methods_1 = require("@metamask/rpc-methods");
|
|
38
36
|
const fsm_2 = require("../fsm");
|
|
39
37
|
const utils_2 = require("../utils");
|
|
40
38
|
const endowments_1 = require("./endowments");
|
|
39
|
+
const rpc_1 = require("./endowments/rpc");
|
|
40
|
+
const location_1 = require("./location");
|
|
41
41
|
const RequestQueue_1 = require("./RequestQueue");
|
|
42
|
-
const utils_3 = require("./utils");
|
|
43
42
|
const Timer_1 = require("./Timer");
|
|
44
43
|
exports.controllerName = 'SnapController';
|
|
45
44
|
// TODO: Figure out how to name these
|
|
@@ -55,7 +54,7 @@ const TRUNCATED_SNAP_PROPERTIES = new Set([
|
|
|
55
54
|
]);
|
|
56
55
|
var AppKeyType;
|
|
57
56
|
(function (AppKeyType) {
|
|
58
|
-
AppKeyType["
|
|
57
|
+
AppKeyType["StateEncryption"] = "stateEncryption";
|
|
59
58
|
})(AppKeyType = exports.AppKeyType || (exports.AppKeyType = {}));
|
|
60
59
|
const defaultState = {
|
|
61
60
|
snapErrors: {},
|
|
@@ -69,12 +68,14 @@ const defaultState = {
|
|
|
69
68
|
* @returns Object with serializable snap properties.
|
|
70
69
|
*/
|
|
71
70
|
function truncateSnap(snap) {
|
|
72
|
-
|
|
71
|
+
const truncatedSnap = Object.keys(snap).reduce((serialized, key) => {
|
|
73
72
|
if (TRUNCATED_SNAP_PROPERTIES.has(key)) {
|
|
74
73
|
serialized[key] = snap[key];
|
|
75
74
|
}
|
|
76
75
|
return serialized;
|
|
77
76
|
}, {});
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
78
|
+
return truncatedSnap;
|
|
78
79
|
}
|
|
79
80
|
const name = 'SnapController';
|
|
80
81
|
/*
|
|
@@ -83,8 +84,8 @@ const name = 'SnapController';
|
|
|
83
84
|
* - Authorize: Requests the snap's required permissions from the user.
|
|
84
85
|
* - Start: Initializes the snap in its SES realm with the authorized permissions.
|
|
85
86
|
*/
|
|
86
|
-
class SnapController extends
|
|
87
|
-
constructor({ closeAllConnections, messenger, state, getAppKey, environmentEndowmentPermissions = [], npmRegistryUrl, idleTimeCheckInterval = (0, utils_1.inMilliseconds)(5, utils_1.Duration.Second), checkBlockList, maxIdleTime = (0, utils_1.inMilliseconds)(30, utils_1.Duration.Second), maxRequestTime = (0, utils_1.inMilliseconds)(60, utils_1.Duration.Second), fetchFunction = globalThis.fetch.bind(globalThis), featureFlags = {}, }) {
|
|
87
|
+
class SnapController extends base_controller_1.BaseControllerV2 {
|
|
88
|
+
constructor({ closeAllConnections, messenger, state, getAppKey, environmentEndowmentPermissions = [], npmRegistryUrl, idleTimeCheckInterval = (0, utils_1.inMilliseconds)(5, utils_1.Duration.Second), checkBlockList, maxIdleTime = (0, utils_1.inMilliseconds)(30, utils_1.Duration.Second), maxRequestTime = (0, utils_1.inMilliseconds)(60, utils_1.Duration.Second), fetchFunction = globalThis.fetch.bind(globalThis), featureFlags = {}, detectSnapLocation: detectSnapLocationFunction = location_1.detectSnapLocation, }) {
|
|
88
89
|
var _a, _b;
|
|
89
90
|
super({
|
|
90
91
|
messenger,
|
|
@@ -135,6 +136,8 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
135
136
|
_SnapController_checkSnapBlockList.set(this, void 0);
|
|
136
137
|
_SnapController_maxIdleTime.set(this, void 0);
|
|
137
138
|
_SnapController_npmRegistryUrl.set(this, void 0);
|
|
139
|
+
_SnapController_detectSnapLocation.set(this, void 0);
|
|
140
|
+
_SnapController_rollbackSnapshots.set(this, void 0);
|
|
138
141
|
_SnapController_getAppKey.set(this, void 0);
|
|
139
142
|
_SnapController_timeoutForLastRequestStatus.set(this, void 0);
|
|
140
143
|
_SnapController_statusMachine.set(this, void 0);
|
|
@@ -148,14 +151,18 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
148
151
|
__classPrivateFieldSet(this, _SnapController_maxIdleTime, maxIdleTime, "f");
|
|
149
152
|
this.maxRequestTime = maxRequestTime;
|
|
150
153
|
__classPrivateFieldSet(this, _SnapController_npmRegistryUrl, npmRegistryUrl, "f");
|
|
154
|
+
__classPrivateFieldSet(this, _SnapController_detectSnapLocation, detectSnapLocationFunction, "f");
|
|
151
155
|
this._onUnhandledSnapError = this._onUnhandledSnapError.bind(this);
|
|
152
156
|
this._onOutboundRequest = this._onOutboundRequest.bind(this);
|
|
153
157
|
this._onOutboundResponse = this._onOutboundResponse.bind(this);
|
|
158
|
+
__classPrivateFieldSet(this, _SnapController_rollbackSnapshots, new Map(), "f");
|
|
154
159
|
this.snapsRuntimeData = new Map();
|
|
155
160
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_pollForLastRequestStatus).call(this);
|
|
161
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
156
162
|
this.messagingSystem.subscribe('ExecutionService:unhandledError', this._onUnhandledSnapError);
|
|
157
163
|
this.messagingSystem.subscribe('ExecutionService:outboundRequest', this._onOutboundRequest);
|
|
158
164
|
this.messagingSystem.subscribe('ExecutionService:outboundResponse', this._onOutboundResponse);
|
|
165
|
+
/* eslint-enable @typescript-eslint/unbound-method */
|
|
159
166
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_initializeStateMachine).call(this);
|
|
160
167
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_registerMessageHandlers).call(this);
|
|
161
168
|
Object.values((_b = state === null || state === void 0 ? void 0 : state.snaps) !== null && _b !== void 0 ? _b : {}).forEach((snap) => {
|
|
@@ -179,7 +186,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
179
186
|
};
|
|
180
187
|
return blockListArg;
|
|
181
188
|
}, {}));
|
|
182
|
-
await Promise.all(Object.entries(blockedSnaps).map((_a) => {
|
|
189
|
+
await Promise.all(Object.entries(blockedSnaps).map(async (_a) => {
|
|
183
190
|
var [snapId, _b] = _a, { blocked } = _b, blockData = __rest(_b, ["blocked"]);
|
|
184
191
|
if (blocked) {
|
|
185
192
|
return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_blockSnap).call(this, snapId, blockData);
|
|
@@ -200,11 +207,15 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
200
207
|
});
|
|
201
208
|
return result[snapId].blocked;
|
|
202
209
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
210
|
+
_onUnhandledSnapError(snapId, error) {
|
|
211
|
+
this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Crash)
|
|
212
|
+
.then(() => this.addSnapError(error))
|
|
213
|
+
.catch((stopSnapError) => {
|
|
214
|
+
// TODO: Decide how to handle errors.
|
|
215
|
+
console.error(stopSnapError);
|
|
216
|
+
});
|
|
206
217
|
}
|
|
207
|
-
|
|
218
|
+
_onOutboundRequest(snapId) {
|
|
208
219
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
209
220
|
// Ideally we would only pause the pending request that is making the outbound request
|
|
210
221
|
// but right now we don't have a way to know which request initiated the outbound request
|
|
@@ -213,7 +224,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
213
224
|
.forEach((pendingRequest) => pendingRequest.timer.pause());
|
|
214
225
|
runtime.pendingOutboundRequests += 1;
|
|
215
226
|
}
|
|
216
|
-
|
|
227
|
+
_onOutboundResponse(snapId) {
|
|
217
228
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
218
229
|
runtime.pendingOutboundRequests -= 1;
|
|
219
230
|
if (runtime.pendingOutboundRequests === 0) {
|
|
@@ -260,7 +271,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
260
271
|
* @param snapId - The id of the Snap to disable.
|
|
261
272
|
* @returns A promise that resolves once the snap has been disabled.
|
|
262
273
|
*/
|
|
263
|
-
disableSnap(snapId) {
|
|
274
|
+
async disableSnap(snapId) {
|
|
264
275
|
if (!this.has(snapId)) {
|
|
265
276
|
throw new Error(`Snap "${snapId}" not found.`);
|
|
266
277
|
}
|
|
@@ -386,7 +397,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
386
397
|
*
|
|
387
398
|
* @param snapId - The id of the Snap whose state should be cleared.
|
|
388
399
|
*/
|
|
389
|
-
|
|
400
|
+
clearSnapState(snapId) {
|
|
390
401
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
391
402
|
runtime.state = null;
|
|
392
403
|
}
|
|
@@ -402,20 +413,19 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
402
413
|
});
|
|
403
414
|
}
|
|
404
415
|
/**
|
|
405
|
-
* Removes an error by internalID from
|
|
416
|
+
* Removes an error by internalID from the SnapControllers state.
|
|
406
417
|
*
|
|
407
418
|
* @param internalID - The internal error ID to remove on the SnapController.
|
|
408
419
|
*/
|
|
409
|
-
|
|
420
|
+
removeSnapError(internalID) {
|
|
410
421
|
this.update((state) => {
|
|
411
422
|
delete state.snapErrors[internalID];
|
|
412
423
|
});
|
|
413
424
|
}
|
|
414
425
|
/**
|
|
415
426
|
* Clears all errors from the SnapControllers state.
|
|
416
|
-
*
|
|
417
427
|
*/
|
|
418
|
-
|
|
428
|
+
clearSnapErrors() {
|
|
419
429
|
this.update((state) => {
|
|
420
430
|
state.snapErrors = {};
|
|
421
431
|
});
|
|
@@ -436,13 +446,13 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
436
446
|
* Completely clear the controller's state: delete all associated data,
|
|
437
447
|
* handlers, event listeners, and permissions; tear down all snap providers.
|
|
438
448
|
*/
|
|
439
|
-
clearState() {
|
|
449
|
+
async clearState() {
|
|
440
450
|
const snapIds = Object.keys(this.state.snaps);
|
|
441
451
|
snapIds.forEach((snapId) => {
|
|
442
452
|
__classPrivateFieldGet(this, _SnapController_closeAllConnections, "f").call(this, snapId);
|
|
443
453
|
});
|
|
444
|
-
this.messagingSystem.call('ExecutionService:terminateAllSnaps');
|
|
445
|
-
snapIds.forEach(this.revokeAllSnapPermissions);
|
|
454
|
+
await this.messagingSystem.call('ExecutionService:terminateAllSnaps');
|
|
455
|
+
snapIds.forEach((snapId) => this.revokeAllSnapPermissions(snapId));
|
|
446
456
|
this.update((state) => {
|
|
447
457
|
state.snaps = {};
|
|
448
458
|
state.snapStates = {};
|
|
@@ -491,8 +501,8 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
491
501
|
*
|
|
492
502
|
* @param snapId - The snap ID.
|
|
493
503
|
*/
|
|
494
|
-
|
|
495
|
-
if (
|
|
504
|
+
revokeAllSnapPermissions(snapId) {
|
|
505
|
+
if (this.messagingSystem.call('PermissionController:hasPermissions', snapId)) {
|
|
496
506
|
this.messagingSystem.call('PermissionController:revokeAllPermissions', snapId);
|
|
497
507
|
}
|
|
498
508
|
}
|
|
@@ -529,9 +539,9 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
529
539
|
* @param origin - The origin whose permitted snaps to retrieve.
|
|
530
540
|
* @returns The serialized permitted snaps for the origin.
|
|
531
541
|
*/
|
|
532
|
-
|
|
542
|
+
getPermittedSnaps(origin) {
|
|
533
543
|
var _a;
|
|
534
|
-
return Object.values((_a =
|
|
544
|
+
return Object.values((_a = this.messagingSystem.call('PermissionController:getPermissions', origin)) !== null && _a !== void 0 ? _a : {}).reduce((permittedSnaps, perm) => {
|
|
535
545
|
if (perm.parentCapability.startsWith(snaps_utils_1.SNAP_PREFIX)) {
|
|
536
546
|
const snapId = perm.parentCapability.replace(snaps_utils_1.SNAP_PREFIX_REGEX, '');
|
|
537
547
|
const snap = this.get(snapId);
|
|
@@ -555,27 +565,46 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
555
565
|
*/
|
|
556
566
|
async installSnaps(origin, requestedSnaps) {
|
|
557
567
|
const result = {};
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
568
|
+
const snapIds = Object.keys(requestedSnaps);
|
|
569
|
+
// Existing snaps may need to be updated
|
|
570
|
+
const pendingUpdates = snapIds.filter((snapId) => this.has(snapId));
|
|
571
|
+
// Non-existing snaps will need to be installed
|
|
572
|
+
const pendingInstalls = snapIds.filter((snapId) => !pendingUpdates.includes(snapId));
|
|
573
|
+
try {
|
|
574
|
+
for (const [snapId, { version: rawVersion }] of Object.entries(requestedSnaps)) {
|
|
575
|
+
const [error, version] = (0, snaps_utils_1.resolveVersionRange)(rawVersion);
|
|
576
|
+
if (error) {
|
|
577
|
+
throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`The "version" field must be a valid SemVer version range if specified. Received: "${rawVersion}".`);
|
|
578
|
+
}
|
|
579
|
+
const permissionName = (0, snaps_utils_1.getSnapPermissionName)(snapId);
|
|
580
|
+
if (!this.messagingSystem.call('PermissionController:hasPermission', origin, permissionName)) {
|
|
581
|
+
throw eth_rpc_errors_1.ethErrors.provider.unauthorized(`Not authorized to install snap "${snapId}". Request the permission for the snap before attempting to install it.`);
|
|
582
|
+
}
|
|
583
|
+
const isUpdate = pendingUpdates.includes(snapId);
|
|
584
|
+
if (isUpdate && __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_isValidUpdate).call(this, snapId, version)) {
|
|
585
|
+
let rollbackSnapshot = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRollbackSnapshot).call(this, snapId);
|
|
586
|
+
if (rollbackSnapshot === undefined) {
|
|
587
|
+
const prevSourceCode = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId).sourceCode;
|
|
588
|
+
rollbackSnapshot = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_createRollbackSnapshot).call(this, snapId);
|
|
589
|
+
rollbackSnapshot.sourceCode = prevSourceCode;
|
|
590
|
+
rollbackSnapshot.newVersion = version;
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
throw new Error('This snap is already being updated.');
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
result[snapId] = await this.processRequestedSnap(origin, snapId, version);
|
|
577
597
|
}
|
|
578
|
-
|
|
598
|
+
snapIds.forEach((snapId) => __classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").delete(snapId));
|
|
599
|
+
}
|
|
600
|
+
catch (error) {
|
|
601
|
+
const installed = pendingInstalls.filter((snapId) => this.has(snapId));
|
|
602
|
+
await this.removeSnaps(installed);
|
|
603
|
+
const snapshottedSnaps = [...__classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").keys()];
|
|
604
|
+
const snapsToRollback = pendingUpdates.filter((snapId) => snapshottedSnaps.includes(snapId));
|
|
605
|
+
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_rollbackSnaps).call(this, snapsToRollback);
|
|
606
|
+
throw error;
|
|
607
|
+
}
|
|
579
608
|
return result;
|
|
580
609
|
}
|
|
581
610
|
/**
|
|
@@ -588,39 +617,22 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
588
617
|
* @returns The resulting snap object, or an error if something went wrong.
|
|
589
618
|
*/
|
|
590
619
|
async processRequestedSnap(origin, snapId, versionRange) {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}
|
|
594
|
-
catch (err) {
|
|
595
|
-
return {
|
|
596
|
-
error: eth_rpc_errors_1.ethErrors.rpc.invalidParams(`"${snapId}" is not a valid snap id.`),
|
|
597
|
-
};
|
|
598
|
-
}
|
|
620
|
+
(0, snaps_utils_1.validateSnapId)(snapId);
|
|
621
|
+
const location = __classPrivateFieldGet(this, _SnapController_detectSnapLocation, "f").call(this, snapId, { versionRange });
|
|
599
622
|
const existingSnap = this.getTruncated(snapId);
|
|
600
623
|
// For devX we always re-install local snaps.
|
|
601
|
-
if (existingSnap &&
|
|
624
|
+
if (existingSnap && !location.shouldAlwaysReload) {
|
|
602
625
|
if ((0, snaps_utils_1.satisfiesVersionRange)(existingSnap.version, versionRange)) {
|
|
603
626
|
return existingSnap;
|
|
604
627
|
}
|
|
605
628
|
if (__classPrivateFieldGet(this, _SnapController_featureFlags, "f").dappsCanUpdateSnaps === true) {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
return {
|
|
610
|
-
error: eth_rpc_errors_1.ethErrors.rpc.invalidParams(`Snap "${snapId}@${existingSnap.version}" is already installed, couldn't update to a version inside requested "${versionRange}" range.`),
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
return updateResult;
|
|
629
|
+
const updateResult = await this.updateSnap(origin, snapId, versionRange, location);
|
|
630
|
+
if (updateResult === null) {
|
|
631
|
+
throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`Snap "${snapId}@${existingSnap.version}" is already installed. Couldn't update to a version inside requested "${versionRange}" range.`);
|
|
614
632
|
}
|
|
615
|
-
|
|
616
|
-
return { error: (0, eth_rpc_errors_1.serializeError)(err) };
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
else {
|
|
620
|
-
return {
|
|
621
|
-
error: eth_rpc_errors_1.ethErrors.rpc.invalidParams(`Version mismatch with already installed snap. ${snapId}@${existingSnap.version} doesn't satisfy requested version ${versionRange}`),
|
|
622
|
-
};
|
|
633
|
+
return updateResult;
|
|
623
634
|
}
|
|
635
|
+
throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`Version mismatch with already installed snap. ${snapId}@${existingSnap.version} doesn't satisfy requested version ${versionRange}.`);
|
|
624
636
|
}
|
|
625
637
|
// Existing snaps must be stopped before overwriting
|
|
626
638
|
if (existingSnap && this.isRunning(snapId)) {
|
|
@@ -630,7 +642,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
630
642
|
const { sourceCode } = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_add).call(this, {
|
|
631
643
|
origin,
|
|
632
644
|
id: snapId,
|
|
633
|
-
|
|
645
|
+
location,
|
|
634
646
|
});
|
|
635
647
|
await this.authorize(origin, snapId);
|
|
636
648
|
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_startSnap).call(this, {
|
|
@@ -641,12 +653,9 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
641
653
|
this.messagingSystem.publish(`SnapController:snapInstalled`, truncated);
|
|
642
654
|
return truncated;
|
|
643
655
|
}
|
|
644
|
-
catch (
|
|
645
|
-
console.error(`Error when adding snap.`,
|
|
646
|
-
|
|
647
|
-
this.removeSnap(snapId);
|
|
648
|
-
}
|
|
649
|
-
return { error: (0, eth_rpc_errors_1.serializeError)(err) };
|
|
656
|
+
catch (error) {
|
|
657
|
+
console.error(`Error when adding snap.`, error);
|
|
658
|
+
throw error;
|
|
650
659
|
}
|
|
651
660
|
}
|
|
652
661
|
/**
|
|
@@ -664,27 +673,29 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
664
673
|
* @param origin - The origin requesting the snap update.
|
|
665
674
|
* @param snapId - The id of the Snap to be updated.
|
|
666
675
|
* @param newVersionRange - A semver version range in which the maximum version will be chosen.
|
|
676
|
+
* @param location - Optional location that was already used during installation flow.
|
|
667
677
|
* @returns The snap metadata if updated, `null` otherwise.
|
|
668
678
|
*/
|
|
669
|
-
async updateSnap(origin, snapId, newVersionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION) {
|
|
679
|
+
async updateSnap(origin, snapId, newVersionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION, location) {
|
|
680
|
+
var _a;
|
|
670
681
|
const snap = this.getExpect(snapId);
|
|
671
|
-
if (!(0, snaps_utils_1.
|
|
682
|
+
if (!(0, snaps_utils_1.isValidSemVerRange)(newVersionRange)) {
|
|
672
683
|
throw new Error(`Received invalid snap version range: "${newVersionRange}".`);
|
|
673
684
|
}
|
|
674
|
-
const newSnap = await this.
|
|
675
|
-
const newVersion = newSnap.manifest.version;
|
|
685
|
+
const newSnap = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_fetchSnap).call(this, snapId, location !== null && location !== void 0 ? location : __classPrivateFieldGet(this, _SnapController_detectSnapLocation, "f").call(this, snapId, { versionRange: newVersionRange }));
|
|
686
|
+
const newVersion = newSnap.manifest.result.version;
|
|
676
687
|
if (!(0, snaps_utils_1.gtVersion)(newVersion, snap.version)) {
|
|
677
688
|
console.warn(`Tried updating snap "${snapId}" within "${newVersionRange}" version range, but newer version "${snap.version}" is already installed`);
|
|
678
689
|
return null;
|
|
679
690
|
}
|
|
680
691
|
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertIsUnblocked).call(this, snapId, {
|
|
681
692
|
version: newVersion,
|
|
682
|
-
shasum: newSnap.manifest.source.shasum,
|
|
693
|
+
shasum: newSnap.manifest.result.source.shasum,
|
|
683
694
|
});
|
|
684
|
-
const processedPermissions = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_processSnapPermissions).call(this, newSnap.manifest.initialPermissions);
|
|
685
|
-
const { newPermissions, unusedPermissions, approvedPermissions } =
|
|
695
|
+
const processedPermissions = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_processSnapPermissions).call(this, newSnap.manifest.result.initialPermissions);
|
|
696
|
+
const { newPermissions, unusedPermissions, approvedPermissions } = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_calculatePermissionsChange).call(this, snapId, processedPermissions);
|
|
686
697
|
const id = (0, nanoid_1.nanoid)();
|
|
687
|
-
const
|
|
698
|
+
const _b = (await this.messagingSystem.call('ApprovalController:addRequest', {
|
|
688
699
|
origin,
|
|
689
700
|
id,
|
|
690
701
|
type: exports.SNAP_APPROVAL_UPDATE,
|
|
@@ -693,12 +704,12 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
693
704
|
metadata: { id, origin: snapId, dappOrigin: origin },
|
|
694
705
|
permissions: newPermissions,
|
|
695
706
|
snapId,
|
|
696
|
-
newVersion: newSnap.manifest.version,
|
|
707
|
+
newVersion: newSnap.manifest.result.version,
|
|
697
708
|
newPermissions,
|
|
698
709
|
approvedPermissions,
|
|
699
710
|
unusedPermissions,
|
|
700
711
|
},
|
|
701
|
-
}, true)), { permissions: approvedNewPermissions } =
|
|
712
|
+
}, true)), { permissions: approvedNewPermissions } = _b, requestData = __rest(_b, ["permissions"]);
|
|
702
713
|
if (this.isRunning(snapId)) {
|
|
703
714
|
await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop);
|
|
704
715
|
}
|
|
@@ -707,53 +718,41 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
707
718
|
origin,
|
|
708
719
|
id: snapId,
|
|
709
720
|
manifest: newSnap.manifest,
|
|
710
|
-
|
|
721
|
+
files: newSnap.files,
|
|
711
722
|
versionRange: newVersionRange,
|
|
723
|
+
isUpdate: true,
|
|
712
724
|
});
|
|
713
725
|
const unusedPermissionsKeys = Object.keys(unusedPermissions);
|
|
714
726
|
if ((0, utils_1.isNonEmptyArray)(unusedPermissionsKeys)) {
|
|
715
|
-
|
|
727
|
+
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
716
728
|
[snapId]: unusedPermissionsKeys,
|
|
717
729
|
});
|
|
718
730
|
}
|
|
719
731
|
if ((0, utils_1.isNonEmptyArray)(Object.keys(approvedNewPermissions))) {
|
|
720
|
-
|
|
732
|
+
this.messagingSystem.call('PermissionController:grantPermissions', {
|
|
721
733
|
approvedPermissions: approvedNewPermissions,
|
|
722
734
|
subject: { origin: snapId },
|
|
723
735
|
requestData,
|
|
724
736
|
});
|
|
725
737
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
*
|
|
736
|
-
* @param snapId - The id of the Snap.
|
|
737
|
-
* @param versionRange - The SemVer version of the Snap to fetch.
|
|
738
|
-
* @returns A tuple of the Snap manifest object and the Snap source code.
|
|
739
|
-
*/
|
|
740
|
-
async fetchSnap(snapId, versionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION) {
|
|
738
|
+
const rollbackSnapshot = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRollbackSnapshot).call(this, snapId);
|
|
739
|
+
if (rollbackSnapshot !== undefined) {
|
|
740
|
+
rollbackSnapshot.permissions.revoked = unusedPermissions;
|
|
741
|
+
rollbackSnapshot.permissions.granted = Object.keys(approvedNewPermissions);
|
|
742
|
+
rollbackSnapshot.permissions.requestData = requestData;
|
|
743
|
+
}
|
|
744
|
+
const sourceCode = (_a = newSnap.files
|
|
745
|
+
.find((file) => file.path === newSnap.manifest.result.source.location.npm.filePath)) === null || _a === void 0 ? void 0 : _a.toString();
|
|
746
|
+
(0, utils_1.assert)(sourceCode !== undefined);
|
|
741
747
|
try {
|
|
742
|
-
|
|
743
|
-
switch (snapPrefix) {
|
|
744
|
-
case snaps_utils_1.SnapIdPrefixes.local:
|
|
745
|
-
return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_fetchLocalSnap).call(this, snapId.replace(snaps_utils_1.SnapIdPrefixes.local, ''));
|
|
746
|
-
case snaps_utils_1.SnapIdPrefixes.npm:
|
|
747
|
-
return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_fetchNpmSnap).call(this, snapId.replace(snaps_utils_1.SnapIdPrefixes.npm, ''), versionRange);
|
|
748
|
-
/* istanbul ignore next */
|
|
749
|
-
default:
|
|
750
|
-
// This whill fail to compile if the above switch is not fully exhaustive
|
|
751
|
-
return (0, utils_1.assertExhaustive)(snapPrefix);
|
|
752
|
-
}
|
|
748
|
+
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_startSnap).call(this, { snapId, sourceCode });
|
|
753
749
|
}
|
|
754
|
-
catch (
|
|
755
|
-
throw new Error(`
|
|
750
|
+
catch (_c) {
|
|
751
|
+
throw new Error(`Snap ${snapId} crashed with updated source code.`);
|
|
756
752
|
}
|
|
753
|
+
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
754
|
+
this.messagingSystem.publish('SnapController:snapUpdated', truncatedSnap, snap.version);
|
|
755
|
+
return truncatedSnap;
|
|
757
756
|
}
|
|
758
757
|
/**
|
|
759
758
|
* Initiates a request for the given snap's initial permissions.
|
|
@@ -785,7 +784,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
785
784
|
},
|
|
786
785
|
}, true)), { permissions: approvedPermissions } = _a, requestData = __rest(_a, ["permissions"]);
|
|
787
786
|
if ((0, utils_1.isNonEmptyArray)(Object.keys(approvedPermissions))) {
|
|
788
|
-
|
|
787
|
+
this.messagingSystem.call('PermissionController:grantPermissions', {
|
|
789
788
|
approvedPermissions,
|
|
790
789
|
subject: { origin: snapId },
|
|
791
790
|
requestData,
|
|
@@ -802,9 +801,11 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
802
801
|
if (__classPrivateFieldGet(this, _SnapController_timeoutForLastRequestStatus, "f")) {
|
|
803
802
|
clearTimeout(__classPrivateFieldGet(this, _SnapController_timeoutForLastRequestStatus, "f"));
|
|
804
803
|
}
|
|
804
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
805
805
|
this.messagingSystem.unsubscribe('ExecutionService:unhandledError', this._onUnhandledSnapError);
|
|
806
806
|
this.messagingSystem.unsubscribe('ExecutionService:outboundRequest', this._onOutboundRequest);
|
|
807
807
|
this.messagingSystem.unsubscribe('ExecutionService:outboundResponse', this._onOutboundResponse);
|
|
808
|
+
/* eslint-enable @typescript-eslint/unbound-method */
|
|
808
809
|
}
|
|
809
810
|
/**
|
|
810
811
|
* Passes a JSON-RPC request object to the RPC handler function of a snap.
|
|
@@ -817,6 +818,23 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
817
818
|
* @returns The result of the JSON-RPC request.
|
|
818
819
|
*/
|
|
819
820
|
async handleRequest({ snapId, origin, handler: handlerType, request, }) {
|
|
821
|
+
const permissionName = endowments_1.handlerEndowments[handlerType];
|
|
822
|
+
const hasPermission = this.messagingSystem.call('PermissionController:hasPermission', snapId, permissionName);
|
|
823
|
+
if (!hasPermission) {
|
|
824
|
+
throw new Error(`Snap "${snapId}" is not permitted to use "${permissionName}".`);
|
|
825
|
+
}
|
|
826
|
+
if (permissionName === endowments_1.SnapEndowments.Rpc) {
|
|
827
|
+
const subject = this.messagingSystem.call('SubjectMetadataController:getSubjectMetadata', origin);
|
|
828
|
+
const isSnap = (subject === null || subject === void 0 ? void 0 : subject.subjectType) === subject_metadata_controller_1.SubjectType.Snap;
|
|
829
|
+
const permissions = this.messagingSystem.call('PermissionController:getPermissions', snapId);
|
|
830
|
+
const rpcPermission = permissions === null || permissions === void 0 ? void 0 : permissions[endowments_1.SnapEndowments.Rpc];
|
|
831
|
+
(0, utils_1.assert)(rpcPermission);
|
|
832
|
+
const origins = (0, rpc_1.getRpcCaveatOrigins)(rpcPermission);
|
|
833
|
+
(0, utils_1.assert)(origins);
|
|
834
|
+
if ((isSnap && !origins.snaps) || (!isSnap && !origins.dapps)) {
|
|
835
|
+
throw new Error(`Snap "${snapId}" is not permitted to handle JSON-RPC requests from "${origin}".`);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
820
838
|
const handler = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRpcRequestHandler).call(this, snapId);
|
|
821
839
|
if (!handler) {
|
|
822
840
|
throw new Error(`Snap RPC message handler not found for snap "${snapId}".`);
|
|
@@ -825,7 +843,7 @@ class SnapController extends controllers_1.BaseControllerV2 {
|
|
|
825
843
|
}
|
|
826
844
|
}
|
|
827
845
|
exports.SnapController = SnapController;
|
|
828
|
-
_SnapController_closeAllConnections = new WeakMap(), _SnapController_environmentEndowmentPermissions = new WeakMap(), _SnapController_featureFlags = new WeakMap(), _SnapController_fetchFunction = new WeakMap(), _SnapController_idleTimeCheckInterval = new WeakMap(), _SnapController_checkSnapBlockList = new WeakMap(), _SnapController_maxIdleTime = new WeakMap(), _SnapController_npmRegistryUrl = new WeakMap(), _SnapController_getAppKey = new WeakMap(), _SnapController_timeoutForLastRequestStatus = new WeakMap(), _SnapController_statusMachine = new WeakMap(), _SnapController_instances = new WeakSet(), _SnapController_initializeStateMachine = function _SnapController_initializeStateMachine() {
|
|
846
|
+
_SnapController_closeAllConnections = new WeakMap(), _SnapController_environmentEndowmentPermissions = new WeakMap(), _SnapController_featureFlags = new WeakMap(), _SnapController_fetchFunction = new WeakMap(), _SnapController_idleTimeCheckInterval = new WeakMap(), _SnapController_checkSnapBlockList = new WeakMap(), _SnapController_maxIdleTime = new WeakMap(), _SnapController_npmRegistryUrl = new WeakMap(), _SnapController_detectSnapLocation = new WeakMap(), _SnapController_rollbackSnapshots = new WeakMap(), _SnapController_getAppKey = new WeakMap(), _SnapController_timeoutForLastRequestStatus = new WeakMap(), _SnapController_statusMachine = new WeakMap(), _SnapController_instances = new WeakSet(), _SnapController_initializeStateMachine = function _SnapController_initializeStateMachine() {
|
|
829
847
|
const disableGuard = ({ snapId }) => {
|
|
830
848
|
return this.getExpect(snapId).enabled;
|
|
831
849
|
};
|
|
@@ -878,23 +896,26 @@ _SnapController_closeAllConnections = new WeakMap(), _SnapController_environment
|
|
|
878
896
|
}, _SnapController_registerMessageHandlers = function _SnapController_registerMessageHandlers() {
|
|
879
897
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:clearSnapState`, (...args) => this.clearSnapState(...args));
|
|
880
898
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:get`, (...args) => this.get(...args));
|
|
881
|
-
this.messagingSystem.registerActionHandler(`${exports.controllerName}:getSnapState`, (...args) => this.getSnapState(...args));
|
|
882
|
-
this.messagingSystem.registerActionHandler(`${exports.controllerName}:handleRequest`, (...args) => this.handleRequest(...args));
|
|
899
|
+
this.messagingSystem.registerActionHandler(`${exports.controllerName}:getSnapState`, async (...args) => this.getSnapState(...args));
|
|
900
|
+
this.messagingSystem.registerActionHandler(`${exports.controllerName}:handleRequest`, async (...args) => this.handleRequest(...args));
|
|
883
901
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:has`, (...args) => this.has(...args));
|
|
884
|
-
this.messagingSystem.registerActionHandler(`${exports.controllerName}:updateBlockedSnaps`, () => this.updateBlockedSnaps());
|
|
885
|
-
this.messagingSystem.registerActionHandler(`${exports.controllerName}:updateSnapState`, (...args) => this.updateSnapState(...args));
|
|
902
|
+
this.messagingSystem.registerActionHandler(`${exports.controllerName}:updateBlockedSnaps`, async () => this.updateBlockedSnaps());
|
|
903
|
+
this.messagingSystem.registerActionHandler(`${exports.controllerName}:updateSnapState`, async (...args) => this.updateSnapState(...args));
|
|
886
904
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:enable`, (...args) => this.enableSnap(...args));
|
|
887
|
-
this.messagingSystem.registerActionHandler(`${exports.controllerName}:disable`, (...args) => this.disableSnap(...args));
|
|
888
|
-
this.messagingSystem.registerActionHandler(`${exports.controllerName}:remove`, (...args) => this.removeSnap(...args));
|
|
905
|
+
this.messagingSystem.registerActionHandler(`${exports.controllerName}:disable`, async (...args) => this.disableSnap(...args));
|
|
906
|
+
this.messagingSystem.registerActionHandler(`${exports.controllerName}:remove`, async (...args) => this.removeSnap(...args));
|
|
889
907
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:getPermitted`, (...args) => this.getPermittedSnaps(...args));
|
|
890
|
-
this.messagingSystem.registerActionHandler(`${exports.controllerName}:install`, (...args) => this.installSnaps(...args));
|
|
908
|
+
this.messagingSystem.registerActionHandler(`${exports.controllerName}:install`, async (...args) => this.installSnaps(...args));
|
|
891
909
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:removeSnapError`, (...args) => this.removeSnapError(...args));
|
|
892
910
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:getAll`, (...args) => this.getAllSnaps(...args));
|
|
893
911
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:incrementActiveReferences`, (...args) => this.incrementActiveReferences(...args));
|
|
894
912
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:decrementActiveReferences`, (...args) => this.decrementActiveReferences(...args));
|
|
895
913
|
}, _SnapController_pollForLastRequestStatus = function _SnapController_pollForLastRequestStatus() {
|
|
896
|
-
__classPrivateFieldSet(this, _SnapController_timeoutForLastRequestStatus, setTimeout(
|
|
897
|
-
|
|
914
|
+
__classPrivateFieldSet(this, _SnapController_timeoutForLastRequestStatus, setTimeout(() => {
|
|
915
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_stopSnapsLastRequestPastMax).call(this).catch((error) => {
|
|
916
|
+
// TODO: Decide how to handle errors.
|
|
917
|
+
console.error(error);
|
|
918
|
+
});
|
|
898
919
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_pollForLastRequestStatus).call(this);
|
|
899
920
|
}, __classPrivateFieldGet(this, _SnapController_idleTimeCheckInterval, "f")), "f");
|
|
900
921
|
}, _SnapController_blockSnap =
|
|
@@ -920,15 +941,7 @@ async function _SnapController_blockSnap(snapId, blockedSnapInfo) {
|
|
|
920
941
|
console.error(`Encountered error when stopping blocked snap "${snapId}".`, error);
|
|
921
942
|
}
|
|
922
943
|
this.messagingSystem.publish(`${exports.controllerName}:snapBlocked`, snapId, blockedSnapInfo);
|
|
923
|
-
}, _SnapController_unblockSnap =
|
|
924
|
-
/**
|
|
925
|
-
* Unblocks a snap so that it can be enabled and started again. Emits
|
|
926
|
-
* {@link SnapUnblocked}. Does nothing if the snap is not installed or already
|
|
927
|
-
* unblocked.
|
|
928
|
-
*
|
|
929
|
-
* @param snapId - The id of the snap to unblock.
|
|
930
|
-
*/
|
|
931
|
-
async function _SnapController_unblockSnap(snapId) {
|
|
944
|
+
}, _SnapController_unblockSnap = function _SnapController_unblockSnap(snapId) {
|
|
932
945
|
if (!this.has(snapId) || !this.state.snaps[snapId].blocked) {
|
|
933
946
|
return;
|
|
934
947
|
}
|
|
@@ -958,7 +971,7 @@ async function _SnapController_assertIsUnblocked(snapId, snapInfo) {
|
|
|
958
971
|
runtime.lastRequest &&
|
|
959
972
|
__classPrivateFieldGet(this, _SnapController_maxIdleTime, "f") &&
|
|
960
973
|
(0, utils_1.timeSince)(runtime.lastRequest) > __classPrivateFieldGet(this, _SnapController_maxIdleTime, "f"))
|
|
961
|
-
.map(([snapId]) => this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop)));
|
|
974
|
+
.map(async ([snapId]) => this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop)));
|
|
962
975
|
}, _SnapController_transition = function _SnapController_transition(snapId, event) {
|
|
963
976
|
const { interpreter } = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
964
977
|
interpreter.send(event);
|
|
@@ -975,16 +988,18 @@ async function _SnapController_terminateSnap(snapId) {
|
|
|
975
988
|
await this.messagingSystem.call('ExecutionService:terminateSnap', snapId);
|
|
976
989
|
this.messagingSystem.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
|
|
977
990
|
}, _SnapController_getEncryptionKey = async function _SnapController_getEncryptionKey(snapId) {
|
|
978
|
-
return __classPrivateFieldGet(this, _SnapController_getAppKey, "f").call(this, snapId, AppKeyType.
|
|
991
|
+
return __classPrivateFieldGet(this, _SnapController_getAppKey, "f").call(this, snapId, AppKeyType.StateEncryption);
|
|
979
992
|
}, _SnapController_encryptSnapState = async function _SnapController_encryptSnapState(snapId, state) {
|
|
980
993
|
const appKey = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getEncryptionKey).call(this, snapId);
|
|
981
|
-
return browser_passworder_1.
|
|
994
|
+
return (0, browser_passworder_1.encrypt)(appKey, state);
|
|
982
995
|
}, _SnapController_decryptSnapState = async function _SnapController_decryptSnapState(snapId, encrypted) {
|
|
983
996
|
const appKey = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getEncryptionKey).call(this, snapId);
|
|
984
997
|
try {
|
|
985
|
-
|
|
998
|
+
const value = await (0, browser_passworder_1.decrypt)(appKey, encrypted);
|
|
999
|
+
(0, utils_1.assert)((0, utils_1.isValidJson)(value));
|
|
1000
|
+
return value;
|
|
986
1001
|
}
|
|
987
|
-
catch (
|
|
1002
|
+
catch (error) {
|
|
988
1003
|
throw new Error('Failed to decrypt snap state, the state must be corrupted.');
|
|
989
1004
|
}
|
|
990
1005
|
}, _SnapController_add =
|
|
@@ -998,15 +1013,8 @@ async function _SnapController_terminateSnap(snapId) {
|
|
|
998
1013
|
* @returns The resulting snap object.
|
|
999
1014
|
*/
|
|
1000
1015
|
async function _SnapController_add(args) {
|
|
1001
|
-
const { id: snapId } = args;
|
|
1016
|
+
const { id: snapId, location } = args;
|
|
1002
1017
|
(0, snaps_utils_1.validateSnapId)(snapId);
|
|
1003
|
-
if (!args ||
|
|
1004
|
-
!('origin' in args) ||
|
|
1005
|
-
!('id' in args) ||
|
|
1006
|
-
(!('manifest' in args) && 'sourceCode' in args) ||
|
|
1007
|
-
('manifest' in args && !('sourceCode' in args))) {
|
|
1008
|
-
throw new Error(`Invalid add snap args for snap "${snapId}".`);
|
|
1009
|
-
}
|
|
1010
1018
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_setupRuntime).call(this, snapId, { sourceCode: null, state: null });
|
|
1011
1019
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
1012
1020
|
if (!runtime.installPromise) {
|
|
@@ -1014,13 +1022,10 @@ async function _SnapController_add(args) {
|
|
|
1014
1022
|
// If fetching and setting the snap succeeds, this property will be set
|
|
1015
1023
|
// to null in the authorize() method.
|
|
1016
1024
|
runtime.installPromise = (async () => {
|
|
1017
|
-
|
|
1018
|
-
return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_set).call(this, Object.assign(Object.assign({}, args), { id: snapId }));
|
|
1019
|
-
}
|
|
1020
|
-
const fetchedSnap = await this.fetchSnap(snapId, args.versionRange);
|
|
1025
|
+
const fetchedSnap = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_fetchSnap).call(this, snapId, location);
|
|
1021
1026
|
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertIsUnblocked).call(this, snapId, {
|
|
1022
|
-
version: fetchedSnap.manifest.version,
|
|
1023
|
-
shasum: fetchedSnap.manifest.source.shasum,
|
|
1027
|
+
version: fetchedSnap.manifest.result.version,
|
|
1028
|
+
shasum: fetchedSnap.manifest.result.source.shasum,
|
|
1024
1029
|
});
|
|
1025
1030
|
return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_set).call(this, Object.assign(Object.assign(Object.assign({}, args), fetchedSnap), { id: snapId }));
|
|
1026
1031
|
})();
|
|
@@ -1044,9 +1049,9 @@ async function _SnapController_add(args) {
|
|
|
1044
1049
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_transition).call(this, snapId, snaps_utils_1.SnapStatusEvents.Start);
|
|
1045
1050
|
return result;
|
|
1046
1051
|
}
|
|
1047
|
-
catch (
|
|
1052
|
+
catch (error) {
|
|
1048
1053
|
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_terminateSnap).call(this, snapId);
|
|
1049
|
-
throw
|
|
1054
|
+
throw error;
|
|
1050
1055
|
}
|
|
1051
1056
|
}, _SnapController_getEndowments =
|
|
1052
1057
|
/**
|
|
@@ -1063,7 +1068,7 @@ async function _SnapController_add(args) {
|
|
|
1063
1068
|
async function _SnapController_getEndowments(snapId) {
|
|
1064
1069
|
let allEndowments = [];
|
|
1065
1070
|
for (const permissionName of __classPrivateFieldGet(this, _SnapController_environmentEndowmentPermissions, "f")) {
|
|
1066
|
-
if (
|
|
1071
|
+
if (this.messagingSystem.call('PermissionController:hasPermission', snapId, permissionName)) {
|
|
1067
1072
|
const endowments = await this.messagingSystem.call('PermissionController:getEndowments', snapId, permissionName);
|
|
1068
1073
|
if (endowments) {
|
|
1069
1074
|
// We don't have any guarantees about the type of the endowments
|
|
@@ -1080,30 +1085,30 @@ async function _SnapController_getEndowments(snapId) {
|
|
|
1080
1085
|
...new Set([...snaps_utils_1.DEFAULT_ENDOWMENTS, ...allEndowments]),
|
|
1081
1086
|
];
|
|
1082
1087
|
if (dedupedEndowments.length <
|
|
1088
|
+
// This is a bug in TypeScript: https://github.com/microsoft/TypeScript/issues/48313
|
|
1089
|
+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
1083
1090
|
snaps_utils_1.DEFAULT_ENDOWMENTS.length + allEndowments.length) {
|
|
1084
1091
|
console.error('Duplicate endowments found. Default endowments should not be requested.', allEndowments);
|
|
1085
1092
|
}
|
|
1086
1093
|
return dedupedEndowments;
|
|
1087
1094
|
}, _SnapController_set = function _SnapController_set(args) {
|
|
1088
|
-
var _a;
|
|
1089
|
-
const { id: snapId, origin, manifest,
|
|
1090
|
-
(0, snaps_utils_1.assertIsSnapManifest)(manifest);
|
|
1091
|
-
const { version } = manifest;
|
|
1095
|
+
var _a, _b;
|
|
1096
|
+
const { id: snapId, origin, manifest, files, versionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION, isUpdate = false, } = args;
|
|
1097
|
+
(0, snaps_utils_1.assertIsSnapManifest)(manifest.result);
|
|
1098
|
+
const { version } = manifest.result;
|
|
1092
1099
|
if (!(0, snaps_utils_1.satisfiesVersionRange)(version, versionRange)) {
|
|
1093
1100
|
throw new Error(`Version mismatch. Manifest for "${snapId}" specifies version "${version}" which doesn't satisfy requested version range "${versionRange}"`);
|
|
1094
1101
|
}
|
|
1102
|
+
const sourceCode = (_a = files
|
|
1103
|
+
.find((file) => file.path === manifest.result.source.location.npm.filePath)) === null || _a === void 0 ? void 0 : _a.toString();
|
|
1104
|
+
const svgIcon = files.find((file) => file.path === manifest.result.source.location.npm.iconPath);
|
|
1105
|
+
(0, utils_1.assert)(sourceCode !== undefined);
|
|
1095
1106
|
if (typeof sourceCode !== 'string' || sourceCode.length === 0) {
|
|
1096
1107
|
throw new Error(`Invalid source code for snap "${snapId}".`);
|
|
1097
1108
|
}
|
|
1098
|
-
const initialPermissions = manifest === null || manifest === void 0 ? void 0 : manifest.initialPermissions;
|
|
1099
|
-
if (!initialPermissions ||
|
|
1100
|
-
typeof initialPermissions !== 'object' ||
|
|
1101
|
-
Array.isArray(initialPermissions)) {
|
|
1102
|
-
throw new Error(`Invalid initial permissions for snap "${snapId}".`);
|
|
1103
|
-
}
|
|
1104
1109
|
const snapsState = this.state.snaps;
|
|
1105
1110
|
const existingSnap = snapsState[snapId];
|
|
1106
|
-
const previousVersionHistory = (
|
|
1111
|
+
const previousVersionHistory = (_b = existingSnap === null || existingSnap === void 0 ? void 0 : existingSnap.versionHistory) !== null && _b !== void 0 ? _b : [];
|
|
1107
1112
|
const versionHistory = [
|
|
1108
1113
|
...previousVersionHistory,
|
|
1109
1114
|
{
|
|
@@ -1117,52 +1122,54 @@ async function _SnapController_getEndowments(snapId) {
|
|
|
1117
1122
|
// previous state.
|
|
1118
1123
|
blocked: false, enabled: true,
|
|
1119
1124
|
// So we can easily correlate the snap with its permission
|
|
1120
|
-
permissionName: (0, snaps_utils_1.getSnapPermissionName)(snapId), id: snapId, initialPermissions,
|
|
1121
|
-
manifest, status: __classPrivateFieldGet(this, _SnapController_statusMachine, "f").config.initial, version,
|
|
1125
|
+
permissionName: (0, snaps_utils_1.getSnapPermissionName)(snapId), id: snapId, initialPermissions: manifest.result.initialPermissions, manifest: manifest.result, status: __classPrivateFieldGet(this, _SnapController_statusMachine, "f").config.initial, version,
|
|
1122
1126
|
versionHistory });
|
|
1123
1127
|
// If the snap was blocked, it isn't any longer
|
|
1124
1128
|
delete snap.blockInformation;
|
|
1125
1129
|
// store the snap back in state
|
|
1126
|
-
this.update((state) => {
|
|
1130
|
+
const { inversePatches } = this.update((state) => {
|
|
1127
1131
|
state.snaps[snapId] = snap;
|
|
1128
1132
|
});
|
|
1133
|
+
// checking for isUpdate here as this function is also used in
|
|
1134
|
+
// the install flow, we do not care to create snapshots for installs
|
|
1135
|
+
if (isUpdate) {
|
|
1136
|
+
const rollbackSnapshot = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRollbackSnapshot).call(this, snapId);
|
|
1137
|
+
if (rollbackSnapshot !== undefined) {
|
|
1138
|
+
rollbackSnapshot.statePatches = inversePatches;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1129
1141
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
1130
1142
|
runtime.sourceCode = sourceCode;
|
|
1131
|
-
this.messagingSystem.publish(`SnapController:snapAdded`, snap, svgIcon);
|
|
1143
|
+
this.messagingSystem.publish(`SnapController:snapAdded`, snap, svgIcon === null || svgIcon === void 0 ? void 0 : svgIcon.toString());
|
|
1132
1144
|
return Object.assign(Object.assign({}, snap), { sourceCode });
|
|
1133
|
-
},
|
|
1134
|
-
if (!(0, snaps_utils_1.isValidSnapVersionRange)(versionRange)) {
|
|
1135
|
-
throw new Error(`Received invalid Snap version range: "${versionRange}".`);
|
|
1136
|
-
}
|
|
1137
|
-
const { manifest, sourceCode, svgIcon } = await (0, utils_3.fetchNpmSnap)(packageName, versionRange, __classPrivateFieldGet(this, _SnapController_npmRegistryUrl, "f"), __classPrivateFieldGet(this, _SnapController_fetchFunction, "f"));
|
|
1138
|
-
return { manifest, sourceCode, svgIcon };
|
|
1139
|
-
}, _SnapController_fetchLocalSnap =
|
|
1145
|
+
}, _SnapController_fetchSnap =
|
|
1140
1146
|
/**
|
|
1141
|
-
* Fetches the manifest and source code of a
|
|
1147
|
+
* Fetches the manifest and source code of a snap.
|
|
1148
|
+
*
|
|
1149
|
+
* This function is not hash private yet because of tests.
|
|
1142
1150
|
*
|
|
1143
|
-
* @param
|
|
1144
|
-
* @
|
|
1151
|
+
* @param snapId - The id of the Snap.
|
|
1152
|
+
* @param location - Source from which snap will be fetched.
|
|
1153
|
+
* @returns A tuple of the Snap manifest object and the Snap source code.
|
|
1145
1154
|
*/
|
|
1146
|
-
async function
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
(0, snaps_utils_1.validateSnapShasum)(manifest, sourceCode);
|
|
1165
|
-
return { manifest, sourceCode, svgIcon };
|
|
1155
|
+
async function _SnapController_fetchSnap(snapId, location) {
|
|
1156
|
+
try {
|
|
1157
|
+
const manifest = await location.manifest();
|
|
1158
|
+
const sourceCode = await location.fetch(manifest.result.source.location.npm.filePath);
|
|
1159
|
+
(0, snaps_utils_1.validateSnapShasum)(manifest.result, sourceCode.toString());
|
|
1160
|
+
const { iconPath } = manifest.result.source.location.npm;
|
|
1161
|
+
const files = [sourceCode];
|
|
1162
|
+
if (iconPath) {
|
|
1163
|
+
files.push(await location.fetch(iconPath));
|
|
1164
|
+
}
|
|
1165
|
+
return { manifest, files, location };
|
|
1166
|
+
}
|
|
1167
|
+
catch (error) {
|
|
1168
|
+
// TODO(ritave): Export `getErrorMessage()` from @metamask/utils and use it here
|
|
1169
|
+
// https://github.com/MetaMask/utils/blob/62d022ef83c91fa4d150e51913be4441508a0ab1/src/assert.ts
|
|
1170
|
+
const message = error instanceof Error ? error.message : error.toString();
|
|
1171
|
+
throw new Error(`Failed to fetch Snap "${snapId}": ${message}.`);
|
|
1172
|
+
}
|
|
1166
1173
|
}, _SnapController_processSnapPermissions = function _SnapController_processSnapPermissions(initialPermissions) {
|
|
1167
1174
|
return (0, snaps_utils_1.fromEntries)(Object.entries(initialPermissions).map(([initialPermission, value]) => {
|
|
1168
1175
|
if ((0, utils_1.hasProperty)(rpc_methods_1.caveatMappers, initialPermission)) {
|
|
@@ -1174,17 +1181,13 @@ async function _SnapController_fetchLocalSnap(localhostUrl) {
|
|
|
1174
1181
|
endowments_1.endowmentCaveatMappers[initialPermission](value),
|
|
1175
1182
|
];
|
|
1176
1183
|
}
|
|
1177
|
-
|
|
1178
|
-
return [
|
|
1184
|
+
// If we have no mapping, this may be a non-snap permission, return as-is
|
|
1185
|
+
return [
|
|
1186
|
+
initialPermission,
|
|
1187
|
+
value,
|
|
1188
|
+
];
|
|
1179
1189
|
}));
|
|
1180
|
-
}, _SnapController_getRpcRequestHandler =
|
|
1181
|
-
/**
|
|
1182
|
-
* Gets the RPC message handler for the given snap.
|
|
1183
|
-
*
|
|
1184
|
-
* @param snapId - The id of the Snap whose message handler to get.
|
|
1185
|
-
* @returns The RPC handler for the given snap.
|
|
1186
|
-
*/
|
|
1187
|
-
async function _SnapController_getRpcRequestHandler(snapId) {
|
|
1190
|
+
}, _SnapController_getRpcRequestHandler = function _SnapController_getRpcRequestHandler(snapId) {
|
|
1188
1191
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
1189
1192
|
const existingHandler = runtime.rpcHandler;
|
|
1190
1193
|
if (existingHandler) {
|
|
@@ -1201,7 +1204,7 @@ async function _SnapController_getRpcRequestHandler(snapId) {
|
|
|
1201
1204
|
if (this.state.snaps[snapId].status === snaps_utils_1.SnapStatus.Installing) {
|
|
1202
1205
|
throw new Error(`Snap "${snapId}" is currently being installed. Please try again later.`);
|
|
1203
1206
|
}
|
|
1204
|
-
if (this.isRunning(snapId)
|
|
1207
|
+
if (!this.isRunning(snapId)) {
|
|
1205
1208
|
let localStartPromise = startPromises.get(snapId);
|
|
1206
1209
|
if (!localStartPromise) {
|
|
1207
1210
|
localStartPromise = this.startSnap(snapId);
|
|
@@ -1241,9 +1244,9 @@ async function _SnapController_getRpcRequestHandler(snapId) {
|
|
|
1241
1244
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_recordSnapRpcRequestFinish).call(this, snapId, request.id);
|
|
1242
1245
|
return result;
|
|
1243
1246
|
}
|
|
1244
|
-
catch (
|
|
1247
|
+
catch (error) {
|
|
1245
1248
|
await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Crash);
|
|
1246
|
-
throw
|
|
1249
|
+
throw error;
|
|
1247
1250
|
}
|
|
1248
1251
|
};
|
|
1249
1252
|
runtime.rpcHandler = rpcHandler;
|
|
@@ -1260,7 +1263,7 @@ async function _SnapController_getRpcRequestHandler(snapId) {
|
|
|
1260
1263
|
* @template PromiseValue - The value of the Promise.
|
|
1261
1264
|
*/
|
|
1262
1265
|
async function _SnapController_executeWithTimeout(snapId, promise, timer) {
|
|
1263
|
-
const isLongRunning =
|
|
1266
|
+
const isLongRunning = this.messagingSystem.call('PermissionController:hasPermission', snapId, endowments_1.SnapEndowments.LongRunning);
|
|
1264
1267
|
// Long running snaps have timeouts disabled
|
|
1265
1268
|
if (isLongRunning) {
|
|
1266
1269
|
return promise;
|
|
@@ -1276,10 +1279,76 @@ async function _SnapController_executeWithTimeout(snapId, promise, timer) {
|
|
|
1276
1279
|
runtime.lastRequest = null;
|
|
1277
1280
|
}, _SnapController_recordSnapRpcRequestFinish = function _SnapController_recordSnapRpcRequestFinish(snapId, requestId) {
|
|
1278
1281
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
1279
|
-
runtime.pendingInboundRequests = runtime.pendingInboundRequests.filter((
|
|
1282
|
+
runtime.pendingInboundRequests = runtime.pendingInboundRequests.filter((request) => request.requestId !== requestId);
|
|
1280
1283
|
if (runtime.pendingInboundRequests.length === 0) {
|
|
1281
1284
|
runtime.lastRequest = Date.now();
|
|
1282
1285
|
}
|
|
1286
|
+
}, _SnapController_getRollbackSnapshot = function _SnapController_getRollbackSnapshot(snapId) {
|
|
1287
|
+
return __classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").get(snapId);
|
|
1288
|
+
}, _SnapController_createRollbackSnapshot = function _SnapController_createRollbackSnapshot(snapId) {
|
|
1289
|
+
(0, utils_1.assert)(__classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").get(snapId) === undefined, new Error(`Snap "${snapId}" rollback snapshot already exists.`));
|
|
1290
|
+
__classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").set(snapId, {
|
|
1291
|
+
statePatches: [],
|
|
1292
|
+
sourceCode: '',
|
|
1293
|
+
permissions: { revoked: null, granted: [], requestData: null },
|
|
1294
|
+
newVersion: '',
|
|
1295
|
+
});
|
|
1296
|
+
const newRollbackSnapshot = __classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").get(snapId);
|
|
1297
|
+
(0, utils_1.assert)(newRollbackSnapshot !== undefined, new Error(`Snapshot creation failed for ${snapId}.`));
|
|
1298
|
+
return newRollbackSnapshot;
|
|
1299
|
+
}, _SnapController_rollbackSnap =
|
|
1300
|
+
/**
|
|
1301
|
+
* Rolls back a snap to its previous state, permissions
|
|
1302
|
+
* and source code based on the `RollbackSnapshot` that
|
|
1303
|
+
* is captured during the update process. After rolling back,
|
|
1304
|
+
* the function also emits an event indicating that the
|
|
1305
|
+
* snap has been rolled back and it clears the snapshot
|
|
1306
|
+
* for that snap.
|
|
1307
|
+
*
|
|
1308
|
+
* @param snapId - The snap id.
|
|
1309
|
+
* @throws {@link Error}. If a snapshot does not exist.
|
|
1310
|
+
*/
|
|
1311
|
+
async function _SnapController_rollbackSnap(snapId) {
|
|
1312
|
+
var _a;
|
|
1313
|
+
const rollbackSnapshot = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRollbackSnapshot).call(this, snapId);
|
|
1314
|
+
if (!rollbackSnapshot) {
|
|
1315
|
+
throw new Error('A snapshot does not exist for this snap.');
|
|
1316
|
+
}
|
|
1317
|
+
await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop);
|
|
1318
|
+
const { statePatches, sourceCode, permissions } = rollbackSnapshot;
|
|
1319
|
+
if (statePatches === null || statePatches === void 0 ? void 0 : statePatches.length) {
|
|
1320
|
+
this.applyPatches(statePatches);
|
|
1321
|
+
}
|
|
1322
|
+
if (sourceCode) {
|
|
1323
|
+
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
1324
|
+
runtime.sourceCode = sourceCode;
|
|
1325
|
+
}
|
|
1326
|
+
if (permissions.revoked && Object.keys(permissions.revoked).length) {
|
|
1327
|
+
this.messagingSystem.call('PermissionController:grantPermissions', {
|
|
1328
|
+
approvedPermissions: permissions.revoked,
|
|
1329
|
+
subject: { origin: snapId },
|
|
1330
|
+
requestData: permissions.requestData,
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
if ((_a = permissions.granted) === null || _a === void 0 ? void 0 : _a.length) {
|
|
1334
|
+
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
1335
|
+
[snapId]: permissions.granted,
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
1339
|
+
this.messagingSystem.publish('SnapController:snapRolledback', truncatedSnap, rollbackSnapshot.newVersion);
|
|
1340
|
+
__classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").delete(snapId);
|
|
1341
|
+
}, _SnapController_rollbackSnaps =
|
|
1342
|
+
/**
|
|
1343
|
+
* Iterates through an array of snap ids
|
|
1344
|
+
* and calls `rollbackSnap` on them.
|
|
1345
|
+
*
|
|
1346
|
+
* @param snapIds - An array of snap ids.
|
|
1347
|
+
*/
|
|
1348
|
+
async function _SnapController_rollbackSnaps(snapIds) {
|
|
1349
|
+
for (const snapId of snapIds) {
|
|
1350
|
+
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_rollbackSnap).call(this, snapId);
|
|
1351
|
+
}
|
|
1283
1352
|
}, _SnapController_getRuntime = function _SnapController_getRuntime(snapId) {
|
|
1284
1353
|
return this.snapsRuntimeData.get(snapId);
|
|
1285
1354
|
}, _SnapController_getRuntimeExpect = function _SnapController_getRuntimeExpect(snapId) {
|
|
@@ -1299,9 +1368,9 @@ async function _SnapController_executeWithTimeout(snapId, promise, timer) {
|
|
|
1299
1368
|
});
|
|
1300
1369
|
(0, fsm_2.forceStrict)(interpreter);
|
|
1301
1370
|
this.snapsRuntimeData.set(snapId, Object.assign({ lastRequest: null, rpcHandler: null, installPromise: null, activeReferences: 0, pendingInboundRequests: [], pendingOutboundRequests: 0, interpreter }, data));
|
|
1302
|
-
}, _SnapController_calculatePermissionsChange =
|
|
1371
|
+
}, _SnapController_calculatePermissionsChange = function _SnapController_calculatePermissionsChange(snapId, desiredPermissionsSet) {
|
|
1303
1372
|
var _a;
|
|
1304
|
-
const oldPermissions = (_a =
|
|
1373
|
+
const oldPermissions = (_a = this.messagingSystem.call('PermissionController:getPermissions', snapId)) !== null && _a !== void 0 ? _a : {};
|
|
1305
1374
|
const newPermissions = (0, utils_2.setDiff)(desiredPermissionsSet, oldPermissions);
|
|
1306
1375
|
// TODO(ritave): The assumption that these are unused only holds so long as we do not
|
|
1307
1376
|
// permit dynamic permission requests.
|
|
@@ -1310,5 +1379,14 @@ async function _SnapController_executeWithTimeout(snapId, promise, timer) {
|
|
|
1310
1379
|
// oldPermissions ∖ (oldPermissions ∖ desiredPermissionsSet) ⟺ oldPermissions ∩ desiredPermissionsSet
|
|
1311
1380
|
const approvedPermissions = (0, utils_2.setDiff)(oldPermissions, unusedPermissions);
|
|
1312
1381
|
return { newPermissions, unusedPermissions, approvedPermissions };
|
|
1382
|
+
}, _SnapController_isValidUpdate = function _SnapController_isValidUpdate(snapId, newVersionRange) {
|
|
1383
|
+
const existingSnap = this.getExpect(snapId);
|
|
1384
|
+
if ((0, snaps_utils_1.satisfiesVersionRange)(existingSnap.version, newVersionRange)) {
|
|
1385
|
+
return false;
|
|
1386
|
+
}
|
|
1387
|
+
if ((0, snaps_utils_1.gtRange)(existingSnap.version, newVersionRange)) {
|
|
1388
|
+
return false;
|
|
1389
|
+
}
|
|
1390
|
+
return true;
|
|
1313
1391
|
};
|
|
1314
1392
|
//# sourceMappingURL=SnapController.js.map
|