Skip to content

Commit

Permalink
Support localization files in preinstalled snaps
Browse files Browse the repository at this point in the history
  • Loading branch information
FrederikBolding committed Jan 10, 2024
1 parent c9439e3 commit c61303f
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 6 deletions.
6 changes: 3 additions & 3 deletions packages/snaps-controllers/coverage.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"branches": 91.09,
"functions": 96.49,
"lines": 97.77,
"branches": 90.96,
"functions": 96.51,
"lines": 97.78,
"statements": 97.46
}
108 changes: 108 additions & 0 deletions packages/snaps-controllers/src/snaps/SnapController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
getMockSnapFilesWithUpdatedChecksum,
MOCK_SNAP_NAME,
DEFAULT_SOURCE_PATH,
DEFAULT_ICON_PATH,
} from '@metamask/snaps-utils/test-utils';
import type { SemVerRange, SemVerVersion } from '@metamask/utils';
import {
Expand Down Expand Up @@ -3497,6 +3498,10 @@ describe('SnapController', () => {
path: DEFAULT_SOURCE_PATH,
value: stringToBytes(DEFAULT_SNAP_BUNDLE),
},
{
path: DEFAULT_ICON_PATH,
value: stringToBytes(DEFAULT_SNAP_ICON),
},
],
},
];
Expand Down Expand Up @@ -3561,6 +3566,10 @@ describe('SnapController', () => {
path: DEFAULT_SOURCE_PATH,
value: stringToBytes(DEFAULT_SNAP_BUNDLE),
},
{
path: DEFAULT_ICON_PATH,
value: stringToBytes(DEFAULT_SNAP_ICON),
},
],
},
];
Expand Down Expand Up @@ -3653,6 +3662,105 @@ describe('SnapController', () => {
snapController.destroy();
});

it('supports localized preinstalled snaps', async () => {
const rootMessenger = getControllerMessenger();
jest.spyOn(rootMessenger, 'call');

// The snap should not have permission initially
rootMessenger.registerActionHandler(
'PermissionController:getPermissions',
() => ({}),
);

const { manifest } = await getMockSnapFilesWithUpdatedChecksum({
manifest: getSnapManifest({
proposedName: '{{ proposedName }}',
locales: ['locales/en.json'],
}),
localizationFiles: [getMockLocalizationFile()],
});

const preinstalledSnaps = [
{
snapId: MOCK_SNAP_ID,
manifest: manifest.result,
files: [
{
path: DEFAULT_SOURCE_PATH,
value: stringToBytes(DEFAULT_SNAP_BUNDLE),
},
{
path: DEFAULT_ICON_PATH,
value: stringToBytes(DEFAULT_SNAP_ICON),
},
{
path: 'locales/en.json',
value: stringToBytes(JSON.stringify(getMockLocalizationFile())),
},
],
},
];

const snapControllerOptions = getSnapControllerWithEESOptions({
preinstalledSnaps,
rootMessenger,
});
const [snapController] = getSnapControllerWithEES(snapControllerOptions);

expect(rootMessenger.call).toHaveBeenCalledWith(
'PermissionController:grantPermissions',
{
approvedPermissions: {
'endowment:rpc': {
caveats: [
{ type: 'rpcOrigin', value: { dapps: false, snaps: true } },
],
},
// eslint-disable-next-line @typescript-eslint/naming-convention
snap_confirm: {},
},
subject: { origin: MOCK_SNAP_ID },
},
);

// After install the snap should have permissions
rootMessenger.registerActionHandler(
'PermissionController:getPermissions',
() => MOCK_SNAP_PERMISSIONS,
);

const result = await snapController.handleRequest({
snapId: MOCK_SNAP_ID,
origin: MOCK_ORIGIN,
request: { method: 'foo' },
handler: HandlerType.OnRpcRequest,
});

expect(result).toContain('foo');

const {
manifest: installedManifest,
localizationFiles: installedLocalizationFiles,
} = snapController.state.snaps[MOCK_SNAP_ID];

assert(installedLocalizationFiles);
const localizedManifest = getLocalizedSnapManifest(
installedManifest,
'en',
installedLocalizationFiles,
);

expect(localizedManifest).toStrictEqual(
getSnapManifest({
proposedName: 'Example Snap',
locales: ['locales/en.json'],
shasum: manifest.result.source.shasum,
}),
);

snapController.destroy();
});

it('authorizes permissions needed for snaps', async () => {
const manifest = getSnapManifest();
const rootMessenger = getControllerMessenger();
Expand Down
20 changes: 17 additions & 3 deletions packages/snaps-controllers/src/snaps/SnapController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1028,22 +1028,36 @@ export class SnapController extends BaseController<

assert(sourceCode, 'Source code not provided for preinstalled snap.');

assert(
!iconPath || (iconPath && svgIcon),
'Icon not provided for preinstalled snap.',
);

assert(
manifest.source.files === undefined,
'Auxiliary files are not currently supported for preinstalled snaps.',
);

const localizationFiles =
manifest.source.locales?.map((path) =>
virtualFiles.find((file) => file.path === path),
) ?? [];

const validatedLocalizationFiles = getValidatedLocalizationFiles(
localizationFiles.filter(Boolean) as VirtualFile<unknown>[],
);

assert(
manifest.source.locales === undefined,
'Localization files are not currently supported for preinstalled snaps.',
localizationFiles.length === validatedLocalizationFiles.length,
'Missing localization files for preinstalled snap.',
);

const filesObject: FetchedSnapFiles = {
manifest: manifestFile,
sourceCode,
svgIcon,
auxiliaryFiles: [],
localizationFiles: [],
localizationFiles: validatedLocalizationFiles,
};

// Add snap to the SnapController state
Expand Down

0 comments on commit c61303f

Please sign in to comment.