@metamask/snaps-controllers 15.0.2 → 16.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 +34 -1
- package/dist/cronjob/CronjobController.cjs +17 -17
- package/dist/cronjob/CronjobController.cjs.map +1 -1
- package/dist/cronjob/CronjobController.d.cts +3 -2
- package/dist/cronjob/CronjobController.d.cts.map +1 -1
- package/dist/cronjob/CronjobController.d.mts +3 -2
- package/dist/cronjob/CronjobController.d.mts.map +1 -1
- package/dist/cronjob/CronjobController.mjs +17 -17
- package/dist/cronjob/CronjobController.mjs.map +1 -1
- package/dist/insights/SnapInsightsController.cjs +8 -8
- package/dist/insights/SnapInsightsController.cjs.map +1 -1
- package/dist/insights/SnapInsightsController.d.cts +3 -2
- package/dist/insights/SnapInsightsController.d.cts.map +1 -1
- package/dist/insights/SnapInsightsController.d.mts +3 -2
- package/dist/insights/SnapInsightsController.d.mts.map +1 -1
- package/dist/insights/SnapInsightsController.mjs +8 -8
- package/dist/insights/SnapInsightsController.mjs.map +1 -1
- package/dist/interface/SnapInterfaceController.cjs +16 -17
- package/dist/interface/SnapInterfaceController.cjs.map +1 -1
- package/dist/interface/SnapInterfaceController.d.cts +3 -2
- package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
- package/dist/interface/SnapInterfaceController.d.mts +3 -2
- package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
- package/dist/interface/SnapInterfaceController.mjs +16 -17
- package/dist/interface/SnapInterfaceController.mjs.map +1 -1
- package/dist/multichain/MultichainRouter.cjs.map +1 -1
- package/dist/multichain/MultichainRouter.d.cts +3 -3
- package/dist/multichain/MultichainRouter.d.cts.map +1 -1
- package/dist/multichain/MultichainRouter.d.mts +3 -3
- package/dist/multichain/MultichainRouter.d.mts.map +1 -1
- package/dist/multichain/MultichainRouter.mjs.map +1 -1
- package/dist/services/ExecutionService.cjs.map +1 -1
- package/dist/services/ExecutionService.d.cts +2 -2
- package/dist/services/ExecutionService.d.cts.map +1 -1
- package/dist/services/ExecutionService.d.mts +2 -2
- package/dist/services/ExecutionService.d.mts.map +1 -1
- package/dist/services/ExecutionService.mjs.map +1 -1
- package/dist/snaps/SnapController.cjs +124 -135
- package/dist/snaps/SnapController.cjs.map +1 -1
- package/dist/snaps/SnapController.d.cts +5 -16
- package/dist/snaps/SnapController.d.cts.map +1 -1
- package/dist/snaps/SnapController.d.mts +5 -16
- package/dist/snaps/SnapController.d.mts.map +1 -1
- package/dist/snaps/SnapController.mjs +126 -137
- package/dist/snaps/SnapController.mjs.map +1 -1
- package/dist/snaps/constants.cjs +12 -1
- package/dist/snaps/constants.cjs.map +1 -1
- package/dist/snaps/constants.d.cts +9 -0
- package/dist/snaps/constants.d.cts.map +1 -1
- package/dist/snaps/constants.d.mts +9 -0
- package/dist/snaps/constants.d.mts.map +1 -1
- package/dist/snaps/constants.mjs +11 -0
- package/dist/snaps/constants.mjs.map +1 -1
- package/dist/snaps/location/npm.cjs +6 -3
- package/dist/snaps/location/npm.cjs.map +1 -1
- package/dist/snaps/location/npm.d.cts +7 -0
- package/dist/snaps/location/npm.d.cts.map +1 -1
- package/dist/snaps/location/npm.d.mts +7 -0
- package/dist/snaps/location/npm.d.mts.map +1 -1
- package/dist/snaps/location/npm.mjs +5 -2
- package/dist/snaps/location/npm.mjs.map +1 -1
- package/dist/snaps/registry/json.cjs +7 -7
- package/dist/snaps/registry/json.cjs.map +1 -1
- package/dist/snaps/registry/json.d.cts +3 -2
- package/dist/snaps/registry/json.d.cts.map +1 -1
- package/dist/snaps/registry/json.d.mts +3 -2
- package/dist/snaps/registry/json.d.mts.map +1 -1
- package/dist/snaps/registry/json.mjs +7 -7
- package/dist/snaps/registry/json.mjs.map +1 -1
- package/dist/websocket/WebSocketService.cjs.map +1 -1
- package/dist/websocket/WebSocketService.d.cts +2 -2
- package/dist/websocket/WebSocketService.d.cts.map +1 -1
- package/dist/websocket/WebSocketService.d.mts +2 -2
- package/dist/websocket/WebSocketService.d.mts.map +1 -1
- package/dist/websocket/WebSocketService.mjs.map +1 -1
- package/package.json +11 -10
|
@@ -5,12 +5,12 @@ import { rpcErrors } from "@metamask/rpc-errors";
|
|
|
5
5
|
import { WALLET_SNAP_PERMISSION_KEY, getMaxRequestTimeCaveat, handlerEndowments, SnapEndowments, getKeyringCaveatOrigins, getRpcCaveatOrigins, processSnapPermissions, getEncryptionEntropy, getChainIdsCaveat } from "@metamask/snaps-rpc-methods";
|
|
6
6
|
import { AuxiliaryFileEncoding, getErrorMessage, OnAssetsLookupResponseStruct } from "@metamask/snaps-sdk";
|
|
7
7
|
import { logWarning, getPlatformVersion, assertIsSnapManifest, assertIsValidSnapId, DEFAULT_ENDOWMENTS, encodeAuxiliaryFile, HandlerType, isOriginAllowed, logError, normalizeRelative, OnTransactionResponseStruct, OnSignatureResponseStruct, resolveVersionRange, SnapCaveatType, SnapStatus, SnapStatusEvents, unwrapError, OnHomePageResponseStruct, getValidatedLocalizationFiles, VirtualFile, NpmSnapFileNames, OnNameLookupResponseStruct, getLocalizedSnapManifest, MAX_FILE_SIZE, OnSettingsPageResponseStruct, isValidUrl, OnAssetHistoricalPriceResponseStruct, OnAssetsConversionResponseStruct, OnAssetsMarketDataResponseStruct } from "@metamask/snaps-utils";
|
|
8
|
-
import {
|
|
8
|
+
import { assert, assertIsJsonRpcRequest, assertStruct, Duration, gtRange, gtVersion, hasProperty, inMilliseconds, isNonEmptyArray, satisfiesVersionRange, timeSince, createDeferredPromise } from "@metamask/utils";
|
|
9
9
|
import { createMachine, interpret } from "@xstate/fsm";
|
|
10
10
|
import { Mutex } from "async-mutex";
|
|
11
11
|
import { nanoid } from "nanoid";
|
|
12
12
|
import { gt, gte } from "semver";
|
|
13
|
-
import { ALLOWED_PERMISSIONS, CLIENT_ONLY_HANDLERS, LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS, METAMASK_ORIGIN, STATE_DEBOUNCE_TIMEOUT } from "./constants.mjs";
|
|
13
|
+
import { ALLOWED_PERMISSIONS, CLIENT_ONLY_HANDLERS, DYNAMIC_PERMISSION_DEPENDENCIES, LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS, METAMASK_ORIGIN, STATE_DEBOUNCE_TIMEOUT } from "./constants.mjs";
|
|
14
14
|
import { detectSnapLocation } from "./location/index.mjs";
|
|
15
15
|
import { SnapsRegistryStatus } from "./registry/index.mjs";
|
|
16
16
|
import { getRunnableSnaps } from "./selectors.mjs";
|
|
@@ -80,20 +80,20 @@ export class SnapController extends BaseController {
|
|
|
80
80
|
#preinstalledSnaps;
|
|
81
81
|
#trackEvent;
|
|
82
82
|
#trackSnapExport;
|
|
83
|
-
constructor({ closeAllConnections, messenger, state, dynamicPermissions = ['
|
|
83
|
+
constructor({ closeAllConnections, messenger, state, dynamicPermissions = ['endowment:caip25', 'wallet_snap'], environmentEndowmentPermissions = [], excludedPermissions = {}, idleTimeCheckInterval = inMilliseconds(5, Duration.Second), maxIdleTime = inMilliseconds(30, Duration.Second), maxRequestTime = inMilliseconds(60, Duration.Second), fetchFunction = globalThis.fetch.bind(undefined), featureFlags = {}, detectSnapLocation: detectSnapLocationFunction = detectSnapLocation, preinstalledSnaps = null, encryptor, getMnemonicSeed, getFeatureFlags = () => ({}), clientCryptography, trackEvent, }) {
|
|
84
84
|
super({
|
|
85
85
|
messenger,
|
|
86
86
|
metadata: {
|
|
87
87
|
snapStates: {
|
|
88
88
|
includeInStateLogs: false,
|
|
89
89
|
persist: true,
|
|
90
|
-
|
|
90
|
+
includeInDebugSnapshot: false,
|
|
91
91
|
usedInUi: false,
|
|
92
92
|
},
|
|
93
93
|
unencryptedSnapStates: {
|
|
94
94
|
includeInStateLogs: false,
|
|
95
95
|
persist: true,
|
|
96
|
-
|
|
96
|
+
includeInDebugSnapshot: false,
|
|
97
97
|
usedInUi: false,
|
|
98
98
|
},
|
|
99
99
|
snaps: {
|
|
@@ -124,7 +124,7 @@ export class SnapController extends BaseController {
|
|
|
124
124
|
return memo;
|
|
125
125
|
}, {}));
|
|
126
126
|
},
|
|
127
|
-
|
|
127
|
+
includeInDebugSnapshot: false,
|
|
128
128
|
// TODO: Ensure larger snap properties are not sent to the UI
|
|
129
129
|
// Currently these are stripped out manually in the extension
|
|
130
130
|
usedInUi: true,
|
|
@@ -159,21 +159,21 @@ export class SnapController extends BaseController {
|
|
|
159
159
|
this.#trackEvent = trackEvent;
|
|
160
160
|
this.#pollForLastRequestStatus();
|
|
161
161
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
162
|
-
this.
|
|
163
|
-
this.
|
|
164
|
-
this.
|
|
162
|
+
this.messenger.subscribe('ExecutionService:unhandledError', this._onUnhandledSnapError);
|
|
163
|
+
this.messenger.subscribe('ExecutionService:outboundRequest', this._onOutboundRequest);
|
|
164
|
+
this.messenger.subscribe('ExecutionService:outboundResponse', this._onOutboundResponse);
|
|
165
165
|
/* eslint-enable @typescript-eslint/unbound-method */
|
|
166
|
-
this.
|
|
166
|
+
this.messenger.subscribe('SnapController:snapInstalled', ({ id }, origin) => {
|
|
167
167
|
this.#callLifecycleHook(origin, id, HandlerType.OnInstall).catch((error) => {
|
|
168
168
|
logError(`Error when calling \`onInstall\` lifecycle hook for snap "${id}": ${getErrorMessage(error)}`);
|
|
169
169
|
});
|
|
170
170
|
});
|
|
171
|
-
this.
|
|
171
|
+
this.messenger.subscribe('SnapController:snapUpdated', ({ id }, _oldVersion, origin) => {
|
|
172
172
|
this.#callLifecycleHook(origin, id, HandlerType.OnUpdate).catch((error) => {
|
|
173
173
|
logError(`Error when calling \`onUpdate\` lifecycle hook for snap "${id}": ${getErrorMessage(error)}`);
|
|
174
174
|
});
|
|
175
175
|
});
|
|
176
|
-
this.
|
|
176
|
+
this.messenger.subscribe('KeyringController:lock', this.#handleLock.bind(this));
|
|
177
177
|
this.#initializeStateMachine();
|
|
178
178
|
this.#registerMessageHandlers();
|
|
179
179
|
Object.values(this.state?.snaps ?? {}).forEach((snap) => this.#setupRuntime(snap.id));
|
|
@@ -181,7 +181,7 @@ export class SnapController extends BaseController {
|
|
|
181
181
|
this.#handlePreinstalledSnaps(this.#preinstalledSnaps);
|
|
182
182
|
}
|
|
183
183
|
this.#trackSnapExport = throttleTracking((snapId, handler, success, origin) => {
|
|
184
|
-
const snapMetadata = this.
|
|
184
|
+
const snapMetadata = this.messenger.call('SnapsRegistry:getMetadata', snapId);
|
|
185
185
|
this.#trackEvent({
|
|
186
186
|
event: 'Snap Export Used',
|
|
187
187
|
category: 'Snaps',
|
|
@@ -264,29 +264,29 @@ export class SnapController extends BaseController {
|
|
|
264
264
|
* actions.
|
|
265
265
|
*/
|
|
266
266
|
#registerMessageHandlers() {
|
|
267
|
-
this.
|
|
268
|
-
this.
|
|
269
|
-
this.
|
|
270
|
-
this.
|
|
271
|
-
this.
|
|
272
|
-
this.
|
|
273
|
-
this.
|
|
274
|
-
this.
|
|
275
|
-
this.
|
|
276
|
-
this.
|
|
277
|
-
this.
|
|
278
|
-
this.
|
|
279
|
-
this.
|
|
280
|
-
this.
|
|
281
|
-
this.
|
|
282
|
-
this.
|
|
283
|
-
this.
|
|
284
|
-
this.
|
|
285
|
-
this.
|
|
286
|
-
this.
|
|
287
|
-
this.
|
|
288
|
-
this.
|
|
289
|
-
this.
|
|
267
|
+
this.messenger.registerActionHandler(`${controllerName}:init`, (...args) => this.init(...args));
|
|
268
|
+
this.messenger.registerActionHandler(`${controllerName}:clearSnapState`, (...args) => this.clearSnapState(...args));
|
|
269
|
+
this.messenger.registerActionHandler(`${controllerName}:get`, (...args) => this.get(...args));
|
|
270
|
+
this.messenger.registerActionHandler(`${controllerName}:getSnapState`, async (...args) => this.getSnapState(...args));
|
|
271
|
+
this.messenger.registerActionHandler(`${controllerName}:handleRequest`, async (...args) => this.handleRequest(...args));
|
|
272
|
+
this.messenger.registerActionHandler(`${controllerName}:has`, (...args) => this.has(...args));
|
|
273
|
+
this.messenger.registerActionHandler(`${controllerName}:updateRegistry`, async () => this.updateRegistry());
|
|
274
|
+
this.messenger.registerActionHandler(`${controllerName}:updateSnapState`, async (...args) => this.updateSnapState(...args));
|
|
275
|
+
this.messenger.registerActionHandler(`${controllerName}:enable`, (...args) => this.enableSnap(...args));
|
|
276
|
+
this.messenger.registerActionHandler(`${controllerName}:disable`, async (...args) => this.disableSnap(...args));
|
|
277
|
+
this.messenger.registerActionHandler(`${controllerName}:remove`, async (...args) => this.removeSnap(...args));
|
|
278
|
+
this.messenger.registerActionHandler(`${controllerName}:getPermitted`, (...args) => this.getPermittedSnaps(...args));
|
|
279
|
+
this.messenger.registerActionHandler(`${controllerName}:install`, async (...args) => this.installSnaps(...args));
|
|
280
|
+
this.messenger.registerActionHandler(`${controllerName}:getAll`, (...args) => this.getAllSnaps(...args));
|
|
281
|
+
this.messenger.registerActionHandler(`${controllerName}:getRunnableSnaps`, (...args) => this.getRunnableSnaps(...args));
|
|
282
|
+
this.messenger.registerActionHandler(`${controllerName}:incrementActiveReferences`, (...args) => this.incrementActiveReferences(...args));
|
|
283
|
+
this.messenger.registerActionHandler(`${controllerName}:decrementActiveReferences`, (...args) => this.decrementActiveReferences(...args));
|
|
284
|
+
this.messenger.registerActionHandler(`${controllerName}:disconnectOrigin`, (...args) => this.removeSnapFromSubject(...args));
|
|
285
|
+
this.messenger.registerActionHandler(`${controllerName}:revokeDynamicPermissions`, (...args) => this.revokeDynamicSnapPermissions(...args));
|
|
286
|
+
this.messenger.registerActionHandler(`${controllerName}:getFile`, async (...args) => this.getSnapFile(...args));
|
|
287
|
+
this.messenger.registerActionHandler(`${controllerName}:stopAllSnaps`, async (...args) => this.stopAllSnaps(...args));
|
|
288
|
+
this.messenger.registerActionHandler(`${controllerName}:isMinimumPlatformVersion`, (...args) => this.isMinimumPlatformVersion(...args));
|
|
289
|
+
this.messenger.registerActionHandler(`${controllerName}:setClientActive`, (...args) => this.setClientActive(...args));
|
|
290
290
|
}
|
|
291
291
|
/**
|
|
292
292
|
* Initialise the SnapController.
|
|
@@ -356,10 +356,10 @@ export class SnapController extends BaseController {
|
|
|
356
356
|
this.#setupRuntime(snapId);
|
|
357
357
|
// Emit events
|
|
358
358
|
if (isUpdate) {
|
|
359
|
-
this.
|
|
359
|
+
this.messenger.publish('SnapController:snapUpdated', this.getTruncatedExpect(snapId), existingSnap.version, METAMASK_ORIGIN, true);
|
|
360
360
|
}
|
|
361
361
|
else {
|
|
362
|
-
this.
|
|
362
|
+
this.messenger.publish('SnapController:snapInstalled', this.getTruncatedExpect(snapId), METAMASK_ORIGIN, true);
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
365
|
}
|
|
@@ -381,8 +381,8 @@ export class SnapController extends BaseController {
|
|
|
381
381
|
*/
|
|
382
382
|
async updateRegistry() {
|
|
383
383
|
this.#assertCanUsePlatform();
|
|
384
|
-
await this.
|
|
385
|
-
const blockedSnaps = await this.
|
|
384
|
+
await this.messenger.call('SnapsRegistry:update');
|
|
385
|
+
const blockedSnaps = await this.messenger.call('SnapsRegistry:get', Object.values(this.state.snaps).reduce((blockListArg, snap) => {
|
|
386
386
|
blockListArg[snap.id] = {
|
|
387
387
|
version: snap.version,
|
|
388
388
|
checksum: snap.manifest.source.shasum,
|
|
@@ -409,6 +409,7 @@ export class SnapController extends BaseController {
|
|
|
409
409
|
versionRange: resolvedVersion,
|
|
410
410
|
fetch: this.#fetchFunction,
|
|
411
411
|
allowLocal: false,
|
|
412
|
+
useNpmProxy: true,
|
|
412
413
|
});
|
|
413
414
|
await this.#updateSnap({
|
|
414
415
|
origin: ORIGIN_METAMASK,
|
|
@@ -441,7 +442,7 @@ export class SnapController extends BaseController {
|
|
|
441
442
|
catch (error) {
|
|
442
443
|
logError(`Encountered error when stopping blocked snap "${snapId}".`, error);
|
|
443
444
|
}
|
|
444
|
-
this.
|
|
445
|
+
this.messenger.publish(`${controllerName}:snapBlocked`, snapId, blockedSnapInfo);
|
|
445
446
|
}
|
|
446
447
|
/**
|
|
447
448
|
* Unblocks a snap so that it can be enabled and started again. Emits
|
|
@@ -458,10 +459,10 @@ export class SnapController extends BaseController {
|
|
|
458
459
|
state.snaps[snapId].blocked = false;
|
|
459
460
|
delete state.snaps[snapId].blockInformation;
|
|
460
461
|
});
|
|
461
|
-
this.
|
|
462
|
+
this.messenger.publish(`${controllerName}:snapUnblocked`, snapId);
|
|
462
463
|
}
|
|
463
464
|
async #assertIsInstallAllowed(snapId, { platformVersion, ...snapInfo }) {
|
|
464
|
-
const results = await this.
|
|
465
|
+
const results = await this.messenger.call('SnapsRegistry:get', {
|
|
465
466
|
[snapId]: snapInfo,
|
|
466
467
|
});
|
|
467
468
|
const result = results[snapId];
|
|
@@ -578,7 +579,7 @@ export class SnapController extends BaseController {
|
|
|
578
579
|
this.update((state) => {
|
|
579
580
|
state.snaps[snapId].enabled = true;
|
|
580
581
|
});
|
|
581
|
-
this.
|
|
582
|
+
this.messenger.publish('SnapController:snapEnabled', this.getTruncatedExpect(snapId));
|
|
582
583
|
}
|
|
583
584
|
/**
|
|
584
585
|
* Disables the given snap. A snap can only be started if it is enabled.
|
|
@@ -596,7 +597,7 @@ export class SnapController extends BaseController {
|
|
|
596
597
|
if (this.isRunning(snapId)) {
|
|
597
598
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
598
599
|
}
|
|
599
|
-
this.
|
|
600
|
+
this.messenger.publish('SnapController:snapDisabled', this.getTruncatedExpect(snapId));
|
|
600
601
|
}
|
|
601
602
|
/**
|
|
602
603
|
* Stops the given snap, removes all hooks, closes all connections, and
|
|
@@ -656,7 +657,7 @@ export class SnapController extends BaseController {
|
|
|
656
657
|
* @param snapId - The snap to terminate.
|
|
657
658
|
*/
|
|
658
659
|
async #terminateSnap(snapId) {
|
|
659
|
-
await this.
|
|
660
|
+
await this.messenger.call('ExecutionService:terminateSnap', snapId);
|
|
660
661
|
// Hack to give up execution for a bit to let gracefully terminating Snaps return.
|
|
661
662
|
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
662
663
|
const runtime = this.#getRuntimeExpect(snapId);
|
|
@@ -666,7 +667,7 @@ export class SnapController extends BaseController {
|
|
|
666
667
|
.forEach((pendingRequest) => pendingRequest.timer.finish());
|
|
667
668
|
// Hack to give up execution for a bit to let timed out requests return.
|
|
668
669
|
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
669
|
-
this.
|
|
670
|
+
this.messenger.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
|
|
670
671
|
}
|
|
671
672
|
/**
|
|
672
673
|
* Returns whether the given snap is running.
|
|
@@ -1051,7 +1052,7 @@ export class SnapController extends BaseController {
|
|
|
1051
1052
|
});
|
|
1052
1053
|
// If the snap has been fully installed before, also emit snapUninstalled.
|
|
1053
1054
|
if (snap.status !== SnapStatus.Installing) {
|
|
1054
|
-
this.
|
|
1055
|
+
this.messenger.publish(`SnapController:snapUninstalled`, truncated);
|
|
1055
1056
|
}
|
|
1056
1057
|
}));
|
|
1057
1058
|
}
|
|
@@ -1067,7 +1068,7 @@ export class SnapController extends BaseController {
|
|
|
1067
1068
|
}
|
|
1068
1069
|
}
|
|
1069
1070
|
#addSnapToSubject(origin, snapId) {
|
|
1070
|
-
const subjectPermissions = this.
|
|
1071
|
+
const subjectPermissions = this.messenger.call('PermissionController:getPermissions', origin);
|
|
1071
1072
|
const existingCaveat = subjectPermissions?.[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);
|
|
1072
1073
|
const subjectHasSnap = Boolean(existingCaveat?.value?.[snapId]);
|
|
1073
1074
|
// If the subject is already connected to the snap, this is a no-op.
|
|
@@ -1076,7 +1077,7 @@ export class SnapController extends BaseController {
|
|
|
1076
1077
|
}
|
|
1077
1078
|
// If an existing caveat exists, we add the snap to that.
|
|
1078
1079
|
if (existingCaveat) {
|
|
1079
|
-
this.
|
|
1080
|
+
this.messenger.call('PermissionController:updateCaveat', origin, WALLET_SNAP_PERMISSION_KEY, SnapCaveatType.SnapIds, { ...existingCaveat.value, [snapId]: {} });
|
|
1080
1081
|
return;
|
|
1081
1082
|
}
|
|
1082
1083
|
const approvedPermissions = {
|
|
@@ -1091,7 +1092,7 @@ export class SnapController extends BaseController {
|
|
|
1091
1092
|
],
|
|
1092
1093
|
},
|
|
1093
1094
|
};
|
|
1094
|
-
this.
|
|
1095
|
+
this.messenger.call('PermissionController:grantPermissions', {
|
|
1095
1096
|
approvedPermissions,
|
|
1096
1097
|
subject: { origin },
|
|
1097
1098
|
});
|
|
@@ -1103,7 +1104,7 @@ export class SnapController extends BaseController {
|
|
|
1103
1104
|
* @param snapId - The id of the snap to remove.
|
|
1104
1105
|
*/
|
|
1105
1106
|
removeSnapFromSubject(origin, snapId) {
|
|
1106
|
-
const subjectPermissions = this.
|
|
1107
|
+
const subjectPermissions = this.messenger.call('PermissionController:getPermissions', origin);
|
|
1107
1108
|
const snapIdsCaveat = subjectPermissions?.[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);
|
|
1108
1109
|
if (!snapIdsCaveat) {
|
|
1109
1110
|
return;
|
|
@@ -1115,10 +1116,10 @@ export class SnapController extends BaseController {
|
|
|
1115
1116
|
};
|
|
1116
1117
|
delete newCaveatValue[snapId];
|
|
1117
1118
|
if (Object.keys(newCaveatValue).length > 0) {
|
|
1118
|
-
this.
|
|
1119
|
+
this.messenger.call('PermissionController:updateCaveat', origin, WALLET_SNAP_PERMISSION_KEY, SnapCaveatType.SnapIds, newCaveatValue);
|
|
1119
1120
|
}
|
|
1120
1121
|
else {
|
|
1121
|
-
this.
|
|
1122
|
+
this.messenger.call('PermissionController:revokePermissions', {
|
|
1122
1123
|
[origin]: [WALLET_SNAP_PERMISSION_KEY],
|
|
1123
1124
|
});
|
|
1124
1125
|
}
|
|
@@ -1133,7 +1134,7 @@ export class SnapController extends BaseController {
|
|
|
1133
1134
|
*/
|
|
1134
1135
|
revokeDynamicSnapPermissions(snapId, permissionNames) {
|
|
1135
1136
|
assert(permissionNames.every((permissionName) => this.#dynamicPermissions.includes(permissionName)), 'Non-dynamic permissions cannot be revoked');
|
|
1136
|
-
this.
|
|
1137
|
+
this.messenger.call('PermissionController:revokePermissions', {
|
|
1137
1138
|
[snapId]: permissionNames,
|
|
1138
1139
|
});
|
|
1139
1140
|
}
|
|
@@ -1143,7 +1144,7 @@ export class SnapController extends BaseController {
|
|
|
1143
1144
|
* @param snapId - The id of the Snap.
|
|
1144
1145
|
*/
|
|
1145
1146
|
#removeSnapFromSubjects(snapId) {
|
|
1146
|
-
const subjects = this.
|
|
1147
|
+
const subjects = this.messenger.call('PermissionController:getSubjectNames');
|
|
1147
1148
|
for (const subject of subjects) {
|
|
1148
1149
|
this.removeSnapFromSubject(subject, snapId);
|
|
1149
1150
|
}
|
|
@@ -1154,8 +1155,8 @@ export class SnapController extends BaseController {
|
|
|
1154
1155
|
* @param snapId - The snap ID.
|
|
1155
1156
|
*/
|
|
1156
1157
|
#revokeAllSnapPermissions(snapId) {
|
|
1157
|
-
if (this.
|
|
1158
|
-
this.
|
|
1158
|
+
if (this.messenger.call('PermissionController:hasPermissions', snapId)) {
|
|
1159
|
+
this.messenger.call('PermissionController:revokeAllPermissions', snapId);
|
|
1159
1160
|
}
|
|
1160
1161
|
}
|
|
1161
1162
|
/**
|
|
@@ -1200,7 +1201,7 @@ export class SnapController extends BaseController {
|
|
|
1200
1201
|
* @returns The serialized permitted snaps for the origin.
|
|
1201
1202
|
*/
|
|
1202
1203
|
getPermittedSnaps(origin) {
|
|
1203
|
-
const permissions = this.
|
|
1204
|
+
const permissions = this.messenger.call('PermissionController:getPermissions', origin) ?? {};
|
|
1204
1205
|
const snaps = permissions[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds)?.value ?? {};
|
|
1205
1206
|
return Object.keys(snaps).reduce((permittedSnaps, snapId) => {
|
|
1206
1207
|
const snap = this.get(snapId);
|
|
@@ -1263,8 +1264,8 @@ export class SnapController extends BaseController {
|
|
|
1263
1264
|
result[snapId] = await this.#processRequestedSnap(origin, snapId, location, version);
|
|
1264
1265
|
}
|
|
1265
1266
|
// Once we finish all installs / updates, emit events.
|
|
1266
|
-
pendingInstalls.forEach((snapId) => this.
|
|
1267
|
-
pendingUpdates.forEach(({ snapId, oldVersion }) => this.
|
|
1267
|
+
pendingInstalls.forEach((snapId) => this.messenger.publish(`SnapController:snapInstalled`, this.getTruncatedExpect(snapId), origin, false));
|
|
1268
|
+
pendingUpdates.forEach(({ snapId, oldVersion }) => this.messenger.publish(`SnapController:snapUpdated`, this.getTruncatedExpect(snapId), oldVersion, origin, false));
|
|
1268
1269
|
snapIds.forEach((snapId) => this.#rollbackSnapshots.delete(snapId));
|
|
1269
1270
|
}
|
|
1270
1271
|
catch (error) {
|
|
@@ -1309,7 +1310,7 @@ export class SnapController extends BaseController {
|
|
|
1309
1310
|
snapId,
|
|
1310
1311
|
type: SNAP_APPROVAL_INSTALL,
|
|
1311
1312
|
});
|
|
1312
|
-
this.
|
|
1313
|
+
this.messenger.publish('SnapController:snapInstallStarted', snapId, origin, false);
|
|
1313
1314
|
// Existing snaps must be stopped before overwriting
|
|
1314
1315
|
if (existingSnap && this.isRunning(snapId)) {
|
|
1315
1316
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
@@ -1350,13 +1351,13 @@ export class SnapController extends BaseController {
|
|
|
1350
1351
|
type: SNAP_APPROVAL_INSTALL,
|
|
1351
1352
|
error: errorString,
|
|
1352
1353
|
});
|
|
1353
|
-
this.
|
|
1354
|
+
this.messenger.publish('SnapController:snapInstallFailed', snapId, origin, false, errorString);
|
|
1354
1355
|
throw error;
|
|
1355
1356
|
}
|
|
1356
1357
|
}
|
|
1357
1358
|
#createApproval({ origin, snapId, type, }) {
|
|
1358
1359
|
const id = nanoid();
|
|
1359
|
-
const promise = this.
|
|
1360
|
+
const promise = this.messenger.call('ApprovalController:addRequest', {
|
|
1360
1361
|
origin,
|
|
1361
1362
|
id,
|
|
1362
1363
|
type,
|
|
@@ -1373,7 +1374,7 @@ export class SnapController extends BaseController {
|
|
|
1373
1374
|
}
|
|
1374
1375
|
#updateApproval(id, requestState) {
|
|
1375
1376
|
try {
|
|
1376
|
-
this.
|
|
1377
|
+
this.messenger.call('ApprovalController:updateRequestState', {
|
|
1377
1378
|
id,
|
|
1378
1379
|
requestState,
|
|
1379
1380
|
});
|
|
@@ -1419,7 +1420,7 @@ export class SnapController extends BaseController {
|
|
|
1419
1420
|
type: SNAP_APPROVAL_UPDATE,
|
|
1420
1421
|
});
|
|
1421
1422
|
try {
|
|
1422
|
-
this.
|
|
1423
|
+
this.messenger.publish('SnapController:snapInstallStarted', snapId, origin, true);
|
|
1423
1424
|
const oldManifest = snap.manifest;
|
|
1424
1425
|
const newSnap = await fetchSnap(snapId, location);
|
|
1425
1426
|
const { sourceCode: sourceCodeFile, manifest: manifestFile } = newSnap;
|
|
@@ -1527,12 +1528,12 @@ export class SnapController extends BaseController {
|
|
|
1527
1528
|
type: SNAP_APPROVAL_UPDATE,
|
|
1528
1529
|
});
|
|
1529
1530
|
}
|
|
1530
|
-
this.
|
|
1531
|
+
this.messenger.publish('SnapController:snapInstallFailed', snapId, origin, true, errorString);
|
|
1531
1532
|
throw error;
|
|
1532
1533
|
}
|
|
1533
1534
|
}
|
|
1534
1535
|
async #resolveAllowlistVersion(snapId, versionRange) {
|
|
1535
|
-
return await this.
|
|
1536
|
+
return await this.messenger.call('SnapsRegistry:resolveVersion', snapId, versionRange);
|
|
1536
1537
|
}
|
|
1537
1538
|
/**
|
|
1538
1539
|
* Returns a promise representing the complete installation of the requested snap.
|
|
@@ -1595,7 +1596,7 @@ export class SnapController extends BaseController {
|
|
|
1595
1596
|
}
|
|
1596
1597
|
try {
|
|
1597
1598
|
const runtime = this.#getRuntimeExpect(snapId);
|
|
1598
|
-
const result = await this.
|
|
1599
|
+
const result = await this.messenger.call('ExecutionService:executeSnap', {
|
|
1599
1600
|
...snapData,
|
|
1600
1601
|
endowments: await this.#getEndowments(snapId),
|
|
1601
1602
|
});
|
|
@@ -1623,8 +1624,8 @@ export class SnapController extends BaseController {
|
|
|
1623
1624
|
async #getEndowments(snapId) {
|
|
1624
1625
|
let allEndowments = [];
|
|
1625
1626
|
for (const permissionName of this.#environmentEndowmentPermissions) {
|
|
1626
|
-
if (this.
|
|
1627
|
-
const endowments = await this.
|
|
1627
|
+
if (this.messenger.call('PermissionController:hasPermission', snapId, permissionName)) {
|
|
1628
|
+
const endowments = await this.messenger.call('PermissionController:getEndowments', snapId, permissionName);
|
|
1628
1629
|
if (endowments) {
|
|
1629
1630
|
// We don't have any guarantees about the type of the endowments
|
|
1630
1631
|
// value, so we have to guard at runtime.
|
|
@@ -1724,7 +1725,7 @@ export class SnapController extends BaseController {
|
|
|
1724
1725
|
// In case the Snap uses a localized manifest, we need to get the
|
|
1725
1726
|
// proposed name from the localized manifest.
|
|
1726
1727
|
const { proposedName } = getLocalizedSnapManifest(manifest.result, 'en', localizedFiles);
|
|
1727
|
-
this.
|
|
1728
|
+
this.messenger.call('SubjectMetadataController:addSubjectMetadata', {
|
|
1728
1729
|
subjectType: SubjectType.Snap,
|
|
1729
1730
|
name: proposedName,
|
|
1730
1731
|
origin: snap.id,
|
|
@@ -1810,11 +1811,11 @@ export class SnapController extends BaseController {
|
|
|
1810
1811
|
clearTimeout(this.#timeoutForLastRequestStatus);
|
|
1811
1812
|
}
|
|
1812
1813
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
1813
|
-
this.
|
|
1814
|
-
this.
|
|
1815
|
-
this.
|
|
1816
|
-
this.
|
|
1817
|
-
this.
|
|
1814
|
+
this.messenger.unsubscribe('ExecutionService:unhandledError', this._onUnhandledSnapError);
|
|
1815
|
+
this.messenger.unsubscribe('ExecutionService:outboundRequest', this._onOutboundRequest);
|
|
1816
|
+
this.messenger.unsubscribe('ExecutionService:outboundResponse', this._onOutboundResponse);
|
|
1817
|
+
this.messenger.clearEventSubscriptions('SnapController:snapInstalled');
|
|
1818
|
+
this.messenger.clearEventSubscriptions('SnapController:snapUpdated');
|
|
1818
1819
|
/* eslint-enable @typescript-eslint/unbound-method */
|
|
1819
1820
|
}
|
|
1820
1821
|
/**
|
|
@@ -1840,7 +1841,7 @@ export class SnapController extends BaseController {
|
|
|
1840
1841
|
assertIsJsonRpcRequest(request);
|
|
1841
1842
|
const permissionName = handlerEndowments[handlerType];
|
|
1842
1843
|
assert(typeof permissionName === 'string' || permissionName === null, "'permissionName' must be either a string or null.");
|
|
1843
|
-
const permissions = this.
|
|
1844
|
+
const permissions = this.messenger.call('PermissionController:getPermissions', snapId);
|
|
1844
1845
|
// If permissionName is null, the handler does not require a permission.
|
|
1845
1846
|
if (permissionName !== null &&
|
|
1846
1847
|
(!permissions || !hasProperty(permissions, permissionName))) {
|
|
@@ -1852,7 +1853,7 @@ export class SnapController extends BaseController {
|
|
|
1852
1853
|
if (permissionName === SnapEndowments.Rpc ||
|
|
1853
1854
|
permissionName === SnapEndowments.Keyring) {
|
|
1854
1855
|
assert(handlerPermissions);
|
|
1855
|
-
const subject = this.
|
|
1856
|
+
const subject = this.messenger.call('SubjectMetadataController:getSubjectMetadata', origin);
|
|
1856
1857
|
const origins = permissionName === SnapEndowments.Rpc
|
|
1857
1858
|
? getRpcCaveatOrigins(handlerPermissions)
|
|
1858
1859
|
: getKeyringCaveatOrigins(handlerPermissions);
|
|
@@ -1890,7 +1891,7 @@ export class SnapController extends BaseController {
|
|
|
1890
1891
|
const transformedRequest = this.#transformSnapRpcRequest(snapId, handlerType, request);
|
|
1891
1892
|
const timer = new Timer(timeout);
|
|
1892
1893
|
this.#recordSnapRpcRequestStart(snapId, transformedRequest.id, timer);
|
|
1893
|
-
const handleRpcRequestPromise = this.
|
|
1894
|
+
const handleRpcRequestPromise = this.messenger.call('ExecutionService:handleRpcRequest', snapId, { origin, handler: handlerType, request: transformedRequest });
|
|
1894
1895
|
// This will either get the result or reject due to the timeout.
|
|
1895
1896
|
try {
|
|
1896
1897
|
const result = await withTimeout(handleRpcRequestPromise, timer);
|
|
@@ -1954,11 +1955,11 @@ export class SnapController extends BaseController {
|
|
|
1954
1955
|
* @returns An identifier that can be used to identify the interface.
|
|
1955
1956
|
*/
|
|
1956
1957
|
async #createInterface(snapId, content, contentType) {
|
|
1957
|
-
return this.
|
|
1958
|
+
return this.messenger.call('SnapInterfaceController:createInterface', snapId, content, undefined, contentType);
|
|
1958
1959
|
}
|
|
1959
1960
|
#assertInterfaceExists(snapId, id) {
|
|
1960
1961
|
// This will throw if the interface isn't accessible, but we assert nevertheless.
|
|
1961
|
-
assert(this.
|
|
1962
|
+
assert(this.messenger.call('SnapInterfaceController:getInterface', snapId, id));
|
|
1962
1963
|
}
|
|
1963
1964
|
/**
|
|
1964
1965
|
* Transform a RPC response if necessary.
|
|
@@ -2012,7 +2013,7 @@ export class SnapController extends BaseController {
|
|
|
2012
2013
|
* @returns The transformed result.
|
|
2013
2014
|
*/
|
|
2014
2015
|
#transformOnAssetsLookupResult(snapId, { params: requestedParams }, { assets }) {
|
|
2015
|
-
const permissions = this.
|
|
2016
|
+
const permissions = this.messenger.call('PermissionController:getPermissions', snapId);
|
|
2016
2017
|
// We know the permissions are guaranteed to be set here.
|
|
2017
2018
|
assert(permissions);
|
|
2018
2019
|
const permission = permissions[SnapEndowments.Assets];
|
|
@@ -2095,7 +2096,7 @@ export class SnapController extends BaseController {
|
|
|
2095
2096
|
case HandlerType.OnUserInput: {
|
|
2096
2097
|
assert(request.params && hasProperty(request.params, 'id'));
|
|
2097
2098
|
const interfaceId = request.params.id;
|
|
2098
|
-
const { context } = this.
|
|
2099
|
+
const { context } = this.messenger.call('SnapInterfaceController:getInterface', snapId, interfaceId);
|
|
2099
2100
|
return {
|
|
2100
2101
|
...request,
|
|
2101
2102
|
params: { ...request.params, context },
|
|
@@ -2251,7 +2252,7 @@ export class SnapController extends BaseController {
|
|
|
2251
2252
|
// Calling this in reverse order to undo the changes
|
|
2252
2253
|
this.#handleInitialConnections(snapId, newInitialConnections ?? null, previousInitialConnections ?? {});
|
|
2253
2254
|
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
2254
|
-
this.
|
|
2255
|
+
this.messenger.publish('SnapController:snapRolledback', truncatedSnap, rollbackSnapshot.newVersion);
|
|
2255
2256
|
this.#rollbackSnapshots.delete(snapId);
|
|
2256
2257
|
}
|
|
2257
2258
|
/**
|
|
@@ -2300,19 +2301,48 @@ export class SnapController extends BaseController {
|
|
|
2300
2301
|
getStateMutex: new Mutex(),
|
|
2301
2302
|
});
|
|
2302
2303
|
}
|
|
2304
|
+
/**
|
|
2305
|
+
* Get the desired permissions including dynamic permissions. That is, if a
|
|
2306
|
+
* dynamic permission was previously granted and at least one of its
|
|
2307
|
+
* dependencies is still desired, it will be included in the desired
|
|
2308
|
+
* permissions.
|
|
2309
|
+
*
|
|
2310
|
+
* @param oldPermissions - The old permissions.
|
|
2311
|
+
* @param desiredPermissions - The desired permissions.
|
|
2312
|
+
* @returns The desired permissions including dynamic permissions.
|
|
2313
|
+
*/
|
|
2314
|
+
#getDesiredPermissions(oldPermissions, desiredPermissions) {
|
|
2315
|
+
return Object.keys(oldPermissions).reduce((accumulator, permissionName) => {
|
|
2316
|
+
if (this.#dynamicPermissions.includes(permissionName)) {
|
|
2317
|
+
const hasDependencies = hasProperty(DYNAMIC_PERMISSION_DEPENDENCIES, permissionName);
|
|
2318
|
+
const hasDependency = DYNAMIC_PERMISSION_DEPENDENCIES[permissionName]?.some((dependency) => hasProperty(desiredPermissions, dependency));
|
|
2319
|
+
// If the permission doesn't have dependencies, or if at least one of
|
|
2320
|
+
// its dependencies is desired, include it in the desired permissions.
|
|
2321
|
+
// NOTE: This effectively means that any permissions granted in the manifest
|
|
2322
|
+
// that are considered dynamic, will not be automatically revoked
|
|
2323
|
+
// when the permission is removed from the manifest.
|
|
2324
|
+
// TODO: Deal with this technical debt.
|
|
2325
|
+
if (!hasDependencies || hasDependency) {
|
|
2326
|
+
accumulator[permissionName] = oldPermissions[permissionName];
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
return accumulator;
|
|
2330
|
+
}, desiredPermissions);
|
|
2331
|
+
}
|
|
2303
2332
|
#calculatePermissionsChange(snapId, desiredPermissionsSet) {
|
|
2304
|
-
const oldPermissions = this.
|
|
2305
|
-
const
|
|
2306
|
-
|
|
2307
|
-
//
|
|
2308
|
-
|
|
2333
|
+
const oldPermissions = this.messenger.call('PermissionController:getPermissions', snapId) ?? {};
|
|
2334
|
+
const desiredPermissionsSetWithDynamic = this.#getDesiredPermissions(oldPermissions, desiredPermissionsSet);
|
|
2335
|
+
const newPermissions = permissionsDiff(desiredPermissionsSetWithDynamic, oldPermissions);
|
|
2336
|
+
// TODO: The assumption that these are unused only holds so long as we do
|
|
2337
|
+
// not permit dynamic permission requests.
|
|
2338
|
+
const unusedPermissions = permissionsDiff(oldPermissions, desiredPermissionsSetWithDynamic);
|
|
2309
2339
|
// It's a Set Intersection of oldPermissions and desiredPermissionsSet
|
|
2310
2340
|
// oldPermissions ∖ (oldPermissions ∖ desiredPermissionsSet) ⟺ oldPermissions ∩ desiredPermissionsSet
|
|
2311
2341
|
const approvedPermissions = permissionsDiff(oldPermissions, unusedPermissions);
|
|
2312
2342
|
return { newPermissions, unusedPermissions, approvedPermissions };
|
|
2313
2343
|
}
|
|
2314
2344
|
#isSubjectConnectedToSnap(snapId, origin) {
|
|
2315
|
-
const subjectPermissions = this.
|
|
2345
|
+
const subjectPermissions = this.messenger.call('PermissionController:getPermissions', origin);
|
|
2316
2346
|
const existingCaveat = subjectPermissions?.[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);
|
|
2317
2347
|
return Boolean(existingCaveat?.value?.[snapId]);
|
|
2318
2348
|
}
|
|
@@ -2332,46 +2362,6 @@ export class SnapController extends BaseController {
|
|
|
2332
2362
|
const approvedConnections = setDiff(filteredOldConnections, unusedConnections);
|
|
2333
2363
|
return { newConnections, unusedConnections, approvedConnections };
|
|
2334
2364
|
}
|
|
2335
|
-
/**
|
|
2336
|
-
* Get the permissions to grant to a Snap following an install, update or
|
|
2337
|
-
* rollback.
|
|
2338
|
-
*
|
|
2339
|
-
* @param snapId - The snap ID.
|
|
2340
|
-
* @param newPermissions - The new permissions to be granted.
|
|
2341
|
-
* @returns The permissions to grant to the Snap.
|
|
2342
|
-
*/
|
|
2343
|
-
#getPermissionsToGrant(snapId, newPermissions) {
|
|
2344
|
-
if (Object.keys(newPermissions).includes(SnapEndowments.EthereumProvider)) {
|
|
2345
|
-
// This will return the globally selected network if the Snap doesn't have
|
|
2346
|
-
// one set.
|
|
2347
|
-
const networkClientId = this.messagingSystem.call('SelectedNetworkController:getNetworkClientIdForDomain', snapId);
|
|
2348
|
-
const { configuration } = this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientId);
|
|
2349
|
-
const chainId = hexToNumber(configuration.chainId);
|
|
2350
|
-
// This needs to be assigned to have proper type inference.
|
|
2351
|
-
const modifiedPermissions = {
|
|
2352
|
-
...newPermissions,
|
|
2353
|
-
'endowment:caip25': {
|
|
2354
|
-
caveats: [
|
|
2355
|
-
{
|
|
2356
|
-
type: 'authorizedScopes',
|
|
2357
|
-
value: {
|
|
2358
|
-
requiredScopes: {},
|
|
2359
|
-
optionalScopes: {
|
|
2360
|
-
[`eip155:${chainId}`]: {
|
|
2361
|
-
accounts: [],
|
|
2362
|
-
},
|
|
2363
|
-
},
|
|
2364
|
-
sessionProperties: {},
|
|
2365
|
-
isMultichainOrigin: false,
|
|
2366
|
-
},
|
|
2367
|
-
},
|
|
2368
|
-
],
|
|
2369
|
-
},
|
|
2370
|
-
};
|
|
2371
|
-
return modifiedPermissions;
|
|
2372
|
-
}
|
|
2373
|
-
return newPermissions;
|
|
2374
|
-
}
|
|
2375
2365
|
/**
|
|
2376
2366
|
* Update the permissions for a snap following an install, update or rollback.
|
|
2377
2367
|
*
|
|
@@ -2386,14 +2376,13 @@ export class SnapController extends BaseController {
|
|
|
2386
2376
|
#updatePermissions({ snapId, unusedPermissions = {}, newPermissions = {}, requestData, }) {
|
|
2387
2377
|
const unusedPermissionsKeys = Object.keys(unusedPermissions);
|
|
2388
2378
|
if (isNonEmptyArray(unusedPermissionsKeys)) {
|
|
2389
|
-
this.
|
|
2379
|
+
this.messenger.call('PermissionController:revokePermissions', {
|
|
2390
2380
|
[snapId]: unusedPermissionsKeys,
|
|
2391
2381
|
});
|
|
2392
2382
|
}
|
|
2393
2383
|
if (isNonEmptyArray(Object.keys(newPermissions))) {
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
approvedPermissions,
|
|
2384
|
+
this.messenger.call('PermissionController:grantPermissions', {
|
|
2385
|
+
approvedPermissions: newPermissions,
|
|
2397
2386
|
subject: { origin: snapId },
|
|
2398
2387
|
requestData,
|
|
2399
2388
|
});
|
|
@@ -2434,7 +2423,7 @@ export class SnapController extends BaseController {
|
|
|
2434
2423
|
#callLifecycleHooks(origin, handler) {
|
|
2435
2424
|
const snaps = this.getRunnableSnaps();
|
|
2436
2425
|
for (const { id } of snaps) {
|
|
2437
|
-
const hasLifecycleHooksEndowment = this.
|
|
2426
|
+
const hasLifecycleHooksEndowment = this.messenger.call('PermissionController:hasPermission', id, SnapEndowments.LifecycleHooks);
|
|
2438
2427
|
if (!hasLifecycleHooksEndowment) {
|
|
2439
2428
|
continue;
|
|
2440
2429
|
}
|
|
@@ -2457,7 +2446,7 @@ export class SnapController extends BaseController {
|
|
|
2457
2446
|
async #callLifecycleHook(origin, snapId, handler) {
|
|
2458
2447
|
const permissionName = handlerEndowments[handler];
|
|
2459
2448
|
assert(permissionName, 'Lifecycle hook must have an endowment.');
|
|
2460
|
-
const hasPermission = this.
|
|
2449
|
+
const hasPermission = this.messenger.call('PermissionController:hasPermission', snapId, permissionName);
|
|
2461
2450
|
if (!hasPermission) {
|
|
2462
2451
|
return;
|
|
2463
2452
|
}
|