Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/extension/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,12 @@ async function main(): Promise<void> {
});
drainPromise.catch(logger.error);

await ping(); // Wait for the kernel to be ready
await startDefaultSubcluster(kernelP);
try {
await ping(); // Wait for the kernel to be ready
await startDefaultSubcluster(kernelP);
} catch (error) {
offscreenStream.throw(error as Error).catch(logger.error);
}

try {
await drainPromise;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Kernel } from '@metamask/ocap-kernel';
import { describe, it, expect, vi, beforeEach } from 'vitest';

import { makeKernelCapTP } from './kernel-captp.ts';
import type { CapTPMessage } from './kernel-captp.ts';
import type { CapTPMessage } from '../../types.ts';

describe('makeKernelCapTP', () => {
const mockKernel: Kernel = {} as unknown as Kernel;
Expand Down
1 change: 1 addition & 0 deletions packages/kernel-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type {
JsonRpcCall,
JsonRpcMessage,
PromiseCallbacks,
Promisified,
TypeGuard,
} from './types.ts';
export {
Expand Down
12 changes: 12 additions & 0 deletions packages/kernel-utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ export type PromiseCallbacks<Resolve = unknown> = Omit<
'promise'
>;

/**
* Utility type that wraps all method return types in Promise.
* Methods already returning Promise<T> remain Promise<T>.
*/
export type Promisified<T> = {
[K in keyof T]: T[K] extends (...args: infer A) => Promise<infer R>
? (...args: A) => Promise<R>
: T[K] extends (...args: infer A) => infer R
? (...args: A) => Promise<R>
: T[K];
};

export const EmptyJsonArray = empty(array(UnsafeJsonStruct));

export type EmptyJsonArray = Infer<typeof EmptyJsonArray>;
Expand Down
4 changes: 2 additions & 2 deletions packages/logger/test/ipc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('ipc', () => {
const logger = new Logger({ transports: [mockTransport] });
logger.injectStream(stream as unknown as DuplexStream<LogMessage>);

await waitUntilQuiescent(1000);
await waitUntilQuiescent(10);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incidental change after the root test:dev was failing due to these timeouts being needlessly long.

expect(mockTransport).toHaveBeenCalledWith({
level: 'debug',
message: 'Hello, world!',
Expand All @@ -53,7 +53,7 @@ describe('ipc', () => {
const logger = new Logger({ transports: [mockTransport] });
logger.injectStream(loggerStream as unknown as DuplexStream<LogMessage>);

await waitUntilQuiescent(1000);
await waitUntilQuiescent(10);
expect(mockTransport).toHaveBeenCalledWith({
level: 'debug',
message: 'Hello, world!',
Expand Down
7 changes: 7 additions & 0 deletions packages/omnium-gatherum/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,20 @@
},
"dependencies": {
"@endo/eventual-send": "^1.3.4",
"@endo/exo": "^1.5.12",
"@metamask/kernel-browser-runtime": "workspace:^",
"@metamask/kernel-shims": "workspace:^",
"@metamask/kernel-ui": "workspace:^",
"@metamask/kernel-utils": "workspace:^",
"@metamask/logger": "workspace:^",
"@metamask/ocap-kernel": "workspace:^",
"@metamask/streams": "workspace:^",
"@metamask/superstruct": "^3.2.1",
"@metamask/utils": "^11.9.0",
"immer": "^10.1.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"semver": "^7.7.1",
"ses": "^1.14.0"
},
"devDependencies": {
Expand All @@ -70,6 +76,7 @@
"@types/chrome": "^0.0.313",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@types/semver": "^7.7.1",
"@types/webextension-polyfill": "^0",
"@typescript-eslint/eslint-plugin": "^8.29.0",
"@typescript-eslint/parser": "^8.29.0",
Expand Down
76 changes: 62 additions & 14 deletions packages/omnium-gatherum/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ import type { JsonRpcMessage } from '@metamask/kernel-utils';
import { Logger } from '@metamask/logger';
import { ChromeRuntimeDuplexStream } from '@metamask/streams/browser';

defineGlobals();
import { initializeControllers } from './controllers/index.ts';
import type {
CapletControllerFacet,
CapletManifest,
} from './controllers/index.ts';

const OFFSCREEN_DOCUMENT_PATH = '/offscreen.html';
const logger = new Logger('background');
const globals = defineGlobals();
let bootPromise: Promise<void> | null = null;
let kernelP: Promise<KernelFacade>;
let ping: () => Promise<void>;

// With this we can click the extension action button to wake up the service worker.
chrome.action.onClicked.addListener(() => {
ping?.().catch(logger.error);
omnium.ping?.().catch(logger.error);
});

// Install/update
Expand Down Expand Up @@ -104,12 +107,23 @@ async function main(): Promise<void> {
},
});

kernelP = backgroundCapTP.getKernel();
const kernelP = backgroundCapTP.getKernel();
globals.setKernelP(kernelP);

ping = async (): Promise<void> => {
globals.setPing(async (): Promise<void> => {
const result = await E(kernelP).ping();
logger.info(result);
};
});

try {
const controllers = await initializeControllers({
logger,
kernel: kernelP,
});
globals.setCapletController(controllers.caplet);
} catch (error) {
offscreenStream.throw(error as Error).catch(logger.error);
}

try {
await offscreenStream.drain((message) => {
Expand All @@ -129,31 +143,65 @@ async function main(): Promise<void> {
}
}

type GlobalSetters = {
setKernelP: (value: Promise<KernelFacade>) => void;
setPing: (value: () => Promise<void>) => void;
setCapletController: (value: CapletControllerFacet) => void;
};

/**
* Define globals accessible via the background console.
*
* @returns A device for setting the global values.
*/
function defineGlobals(): void {
function defineGlobals(): GlobalSetters {
Object.defineProperty(globalThis, 'E', {
configurable: false,
enumerable: true,
writable: false,
value: E,
});

Object.defineProperty(globalThis, 'omnium', {
configurable: false,
enumerable: true,
writable: false,
value: {},
});

let kernelP: Promise<KernelFacade>;
let ping: (() => Promise<void>) | undefined;
let capletController: CapletControllerFacet;

Object.defineProperties(globalThis.omnium, {
ping: {
get: () => ping,
},
getKernel: {
value: async () => kernelP,
},
caplet: {
value: harden({
install: async (manifest: CapletManifest) =>
E(capletController).install(manifest),
uninstall: async (capletId: string) =>
E(capletController).uninstall(capletId),
list: async () => E(capletController).list(),
get: async (capletId: string) => E(capletController).get(capletId),
}),
},
});
harden(globalThis.omnium);

Object.defineProperty(globalThis, 'E', {
configurable: false,
enumerable: true,
writable: false,
value: E,
});
return {
setKernelP: (value) => {
kernelP = value;
},
setPing: (value) => {
ping = value;
},
setCapletController: (value) => {
capletController = value;
},
};
}
Loading
Loading