@@ -70,10 +70,13 @@ import {
7070import { hmac } from '@noble/hashes/hmac' ;
7171import { sha512 } from '@noble/hashes/sha512' ;
7272import { File } from 'buffer' ;
73+ import { createReadStream } from 'fs' ;
7374import fetchMock from 'jest-fetch-mock' ;
75+ import path from 'path' ;
7476import { pipeline } from 'readable-stream' ;
7577import type { Duplex } from 'readable-stream' ;
7678import { inc } from 'semver' ;
79+ import { Readable } from 'stream' ;
7780
7881import {
7982 LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS ,
@@ -9953,7 +9956,7 @@ describe('SnapController', () => {
99539956 } ) ;
99549957 } ) ;
99559958
9956- describe ( 'updateBlockedSnaps ' , ( ) => {
9959+ describe ( 'updateRegistry ' , ( ) => {
99579960 it ( 'updates the registry database' , async ( ) => {
99589961 const registry = new MockSnapsRegistry ( ) ;
99599962 const rootMessenger = getControllerMessenger ( registry ) ;
@@ -9967,7 +9970,7 @@ describe('SnapController', () => {
99679970 } ,
99689971 } ) ,
99699972 ) ;
9970- await snapController . updateBlockedSnaps ( ) ;
9973+ await snapController . updateRegistry ( ) ;
99719974
99729975 expect ( registry . update ) . toHaveBeenCalled ( ) ;
99739976
@@ -10011,7 +10014,7 @@ describe('SnapController', () => {
1001110014 reason : { explanation, infoUrl } ,
1001210015 } ,
1001310016 } ) ;
10014- await snapController . updateBlockedSnaps ( ) ;
10017+ await snapController . updateRegistry ( ) ;
1001510018
1001610019 // Ensure that CheckSnapBlockListArg is correct
1001710020 expect ( registry . get ) . toHaveBeenCalledWith ( {
@@ -10070,7 +10073,7 @@ describe('SnapController', () => {
1007010073 registry . get . mockResolvedValueOnce ( {
1007110074 [ mockSnap . id ] : { status : SnapsRegistryStatus . Blocked } ,
1007210075 } ) ;
10073- await snapController . updateBlockedSnaps ( ) ;
10076+ await snapController . updateRegistry ( ) ;
1007410077
1007510078 // The snap is blocked, disabled, and stopped
1007610079 expect ( snapController . get ( mockSnap . id ) ?. blocked ) . toBe ( true ) ;
@@ -10124,7 +10127,7 @@ describe('SnapController', () => {
1012410127 [ mockSnapA . id ] : { status : SnapsRegistryStatus . Unverified } ,
1012510128 [ mockSnapB . id ] : { status : SnapsRegistryStatus . Unverified } ,
1012610129 } ) ;
10127- await snapController . updateBlockedSnaps ( ) ;
10130+ await snapController . updateRegistry ( ) ;
1012810131
1012910132 // A is unblocked, but still disabled
1013010133 expect ( snapController . get ( mockSnapA . id ) ?. blocked ) . toBe ( false ) ;
@@ -10168,7 +10171,7 @@ describe('SnapController', () => {
1016810171 new Promise < unknown > ( ( resolve ) => ( resolveBlockListPromise = resolve ) ) ,
1016910172 ) ;
1017010173
10171- const updateBlockList = snapController . updateBlockedSnaps ( ) ;
10174+ const updateBlockList = snapController . updateRegistry ( ) ;
1017210175
1017310176 // Remove the snap while waiting for the blocklist
1017410177 await snapController . removeSnap ( mockSnap . id ) ;
@@ -10216,7 +10219,7 @@ describe('SnapController', () => {
1021610219 registry . get . mockResolvedValueOnce ( {
1021710220 [ mockSnap . id ] : { status : SnapsRegistryStatus . Blocked } ,
1021810221 } ) ;
10219- await snapController . updateBlockedSnaps ( ) ;
10222+ await snapController . updateRegistry ( ) ;
1022010223
1022110224 // A is blocked and disabled
1022210225 expect ( snapController . get ( mockSnap . id ) ?. blocked ) . toBe ( true ) ;
@@ -10230,6 +10233,131 @@ describe('SnapController', () => {
1023010233
1023110234 snapController . destroy ( ) ;
1023210235 } ) ;
10236+
10237+ it ( 'updates preinstalled Snaps' , async ( ) => {
10238+ const registry = new MockSnapsRegistry ( ) ;
10239+ const rootMessenger = getControllerMessenger ( registry ) ;
10240+ const messenger = getSnapControllerMessenger ( rootMessenger ) ;
10241+
10242+ // Simulate previous permissions, some of which will be removed
10243+ rootMessenger . registerActionHandler (
10244+ 'PermissionController:getPermissions' ,
10245+ ( ) => {
10246+ return {
10247+ [ SnapEndowments . Rpc ] : MOCK_RPC_ORIGINS_PERMISSION ,
10248+ [ SnapEndowments . LifecycleHooks ] : MOCK_LIFECYCLE_HOOKS_PERMISSION ,
10249+ } ;
10250+ } ,
10251+ ) ;
10252+
10253+ const snapId = 'npm:@metamask/jsx-example-snap' as SnapId ;
10254+
10255+ const mockSnap = getPersistedSnapObject ( {
10256+ id : snapId ,
10257+ preinstalled : true ,
10258+ } ) ;
10259+
10260+ const updateVersion = '1.2.1' ;
10261+
10262+ registry . resolveVersion . mockResolvedValue ( updateVersion ) ;
10263+ const fetchFunction = jest . fn ( ) . mockResolvedValueOnce ( {
10264+ // eslint-disable-next-line no-restricted-globals
10265+ headers : new Headers ( { 'content-length' : '5477' } ) ,
10266+ ok : true ,
10267+ body : Readable . toWeb (
10268+ createReadStream (
10269+ path . resolve (
10270+ __dirname ,
10271+ `../../test/fixtures/metamask-jsx-example-snap-${ updateVersion } .tgz` ,
10272+ ) ,
10273+ ) ,
10274+ ) ,
10275+ } ) ;
10276+
10277+ const snapController = getSnapController (
10278+ getSnapControllerOptions ( {
10279+ messenger,
10280+ state : {
10281+ snaps : getPersistedSnapsState ( mockSnap ) ,
10282+ } ,
10283+ fetchFunction,
10284+ featureFlags : {
10285+ autoUpdatePreinstalledSnaps : true ,
10286+ } ,
10287+ } ) ,
10288+ ) ;
10289+
10290+ await snapController . updateRegistry ( ) ;
10291+
10292+ const updatedSnap = snapController . get ( snapId ) ;
10293+ assert ( updatedSnap ) ;
10294+
10295+ expect ( updatedSnap . version ) . toStrictEqual ( updateVersion ) ;
10296+ expect ( updatedSnap . preinstalled ) . toBe ( true ) ;
10297+
10298+ expect ( rootMessenger . call ) . toHaveBeenNthCalledWith (
10299+ 7 ,
10300+ 'PermissionController:revokePermissions' ,
10301+ { [ snapId ] : [ SnapEndowments . Rpc , SnapEndowments . LifecycleHooks ] } ,
10302+ ) ;
10303+ expect ( rootMessenger . call ) . toHaveBeenNthCalledWith (
10304+ 8 ,
10305+ 'PermissionController:grantPermissions' ,
10306+ {
10307+ approvedPermissions : {
10308+ 'endowment:rpc' : {
10309+ caveats : [ { type : 'rpcOrigin' , value : { dapps : true } } ] ,
10310+ } ,
10311+ // eslint-disable-next-line @typescript-eslint/naming-convention
10312+ snap_dialog : { } ,
10313+ // eslint-disable-next-line @typescript-eslint/naming-convention
10314+ snap_manageState : { } ,
10315+ } ,
10316+ subject : { origin : snapId } ,
10317+ } ,
10318+ ) ;
10319+
10320+ snapController . destroy ( ) ;
10321+ } ) ;
10322+
10323+ it ( 'does not update preinstalled Snaps when the feature flag is off' , async ( ) => {
10324+ const registry = new MockSnapsRegistry ( ) ;
10325+ const rootMessenger = getControllerMessenger ( registry ) ;
10326+ const messenger = getSnapControllerMessenger ( rootMessenger ) ;
10327+
10328+ const snapId = 'npm:@metamask/jsx-example-snap' as SnapId ;
10329+
10330+ const mockSnap = getPersistedSnapObject ( {
10331+ id : snapId ,
10332+ preinstalled : true ,
10333+ } ) ;
10334+
10335+ const updateVersion = '1.2.1' ;
10336+
10337+ registry . resolveVersion . mockResolvedValue ( updateVersion ) ;
10338+
10339+ const snapController = getSnapController (
10340+ getSnapControllerOptions ( {
10341+ messenger,
10342+ state : {
10343+ snaps : getPersistedSnapsState ( mockSnap ) ,
10344+ } ,
10345+ featureFlags : {
10346+ autoUpdatePreinstalledSnaps : false ,
10347+ } ,
10348+ } ) ,
10349+ ) ;
10350+
10351+ await snapController . updateRegistry ( ) ;
10352+
10353+ const snap = snapController . get ( snapId ) ;
10354+ assert ( snap ) ;
10355+
10356+ expect ( snap . version ) . toStrictEqual ( mockSnap . version ) ;
10357+ expect ( registry . resolveVersion ) . not . toHaveBeenCalled ( ) ;
10358+
10359+ snapController . destroy ( ) ;
10360+ } ) ;
1023310361 } ) ;
1023410362
1023510363 describe ( 'clearState' , ( ) => {
@@ -11521,21 +11649,21 @@ describe('SnapController', () => {
1152111649 } ) ;
1152211650 } ) ;
1152311651
11524- describe ( 'SnapController:updateBlockedSnaps ' , ( ) => {
11525- it ( 'calls SnapController.updateBlockedSnaps ()' , async ( ) => {
11652+ describe ( 'SnapController:updateRegistry ' , ( ) => {
11653+ it ( 'calls SnapController.updateRegistry ()' , async ( ) => {
1152611654 const messenger = getSnapControllerMessenger ( ) ;
1152711655 const snapController = getSnapController (
1152811656 getSnapControllerOptions ( {
1152911657 messenger,
1153011658 } ) ,
1153111659 ) ;
1153211660
11533- const updateBlockedSnapsSpy = jest
11534- . spyOn ( snapController , 'updateBlockedSnaps ' )
11661+ const updateRegistrySpy = jest
11662+ . spyOn ( snapController , 'updateRegistry ' )
1153511663 . mockImplementation ( ) ;
1153611664
11537- await messenger . call ( 'SnapController:updateBlockedSnaps ' ) ;
11538- expect ( updateBlockedSnapsSpy ) . toHaveBeenCalledTimes ( 1 ) ;
11665+ await messenger . call ( 'SnapController:updateRegistry ' ) ;
11666+ expect ( updateRegistrySpy ) . toHaveBeenCalledTimes ( 1 ) ;
1153911667
1154011668 snapController . destroy ( ) ;
1154111669 } ) ;
0 commit comments