Skip to content

Commit

Permalink
Separate trusted from untrusted client calls
Browse files Browse the repository at this point in the history
  • Loading branch information
Twey committed May 16, 2024
1 parent 209ead3 commit 32504ab
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 36 deletions.
15 changes: 13 additions & 2 deletions client-worker/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
/**
This module defines the client API for the Web extension.
Exported (marked with `#[wasm_bindgen]`) functions will be callable from the extension frontend.
Exported functions prefixed with `dapp_` _will additionally be
callable from all Web pages to which the Web client has been
connected_. Outside of their type, which is checked at call time,
arguments to these functions cannot be trusted and _must_ be verified!
*/

use linera_base::{
crypto::{CryptoRng, CryptoHash, KeyPair, PublicKey},
data_types::{Amount, BlockHeight, Timestamp},
Expand Down Expand Up @@ -165,7 +176,7 @@ impl WalletState {
}

#[wasm_bindgen]
pub async fn query_validators() -> Result<(), JsError> {
pub async fn dapp_query_validators() -> Result<(), JsError> {
let wallet = WALLET.read()?;
let wallet = wallet.as_ref().ok_or(JsError::new("no wallet set"))?;

Expand Down Expand Up @@ -219,7 +230,7 @@ pub async fn set_wallet(wallet: &str) -> Result<(), wasm_bindgen::JsError> {
}

#[wasm_bindgen]
pub async fn query(n: u32) -> u32 {
pub async fn dapp_query(n: u32) -> u32 {
n + 1
}

Expand Down
4 changes: 3 additions & 1 deletion extension/src/content-script/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* TODO make this conform to https://github.com/wallet-standard/wallet-standard/ */

type RequestEvent = CustomEvent<{id: unknown; message: unknown;}>;

function respond(id: unknown, message: unknown) {
Expand All @@ -8,7 +10,7 @@ function respond(id: unknown, message: unknown) {

window.addEventListener('linera-wallet-request', async e => {
const event = e as RequestEvent;
respond(event.detail.id, await chrome.runtime.sendMessage(event.detail.message))
respond(event.detail.id, await chrome.runtime.sendMessage(event.detail.message));
});

window.dispatchEvent(new Event('linera-wallet-loaded'));
13 changes: 13 additions & 0 deletions extension/src/messaging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type CallRequest = {
type: "client_call";
arguments: [any];
function: string;
};

export async function callClientFunction(name: string, ...args: any): Promise<any> {
return await chrome.runtime.sendMessage({
type: "client_call",
function: name,
arguments: args,
});
}
44 changes: 43 additions & 1 deletion extension/src/service-worker/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,43 @@
import './setup.ts';
import * as wasm from './client/linera_web.js';
import initWasm from './client/linera_web.js';

import wasmModuleUrl from './client/linera_web_bg.wasm?url';
import * as messaging from '@/messaging';

chrome.sidePanel.setPanelBehavior({
openPanelOnActionClick: true,
}).catch((error) => console.error(error));

chrome.runtime.onInstalled.addListener(async () => {
const windowId = (await chrome.windows.getCurrent()).id;
if (windowId === undefined) return;
chrome.action.setPopup({ popup: "src/popup/welcome.html" });
await chrome.action.openPopup({ windowId });
});

self.addEventListener("activate", async () => {
await initWasm((await fetch(wasmModuleUrl)).arrayBuffer());
console.log("Client worker initialized");
});

chrome.runtime.onMessage.addListener((message: messaging.CallRequest, sender, respond) => {
let functionName = message.function;

if (sender.origin === self.location.origin) {
console.log("Received message from extension", message);
} else {
console.log("Received message from content script", message);
functionName = "dapp_" + functionName;
}

if (!(functionName in wasm)) {
console.error("Attempted to call undefined function", functionName);
return false;
}

let func = wasm[functionName as keyof typeof wasm] as (...args: any) => any;

func.apply(wasm, message.arguments).then(respond);

return true;
});
25 changes: 0 additions & 25 deletions extension/src/service-worker/setup.ts

This file was deleted.

10 changes: 5 additions & 5 deletions extension/src/sidebar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ import buttonStyles from '@shoelace-style/shoelace/dist/components/button/button
import '@/shoelace.ts';

import * as popup from '@/popup';

type Wallet = {
default: string;
};
import * as messaging from '@/messaging';

@customElement('linera-wallet-picker')
export class WalletPicker extends LitElement {
Expand Down Expand Up @@ -78,7 +75,9 @@ export class ConfirmButton extends LitElement {
@customElement('linera-sidebar')
export class Sidebar extends LitElement {
@state()
wallet?: Wallet;
wallet?: {
default: string;
};

static styles = css`
.chain-id {
Expand Down Expand Up @@ -108,6 +107,7 @@ export class Sidebar extends LitElement {

private async onWalletChange(wallet: string) {
window.localStorage.setItem('wallet', wallet);
messaging.callClientFunction('set_wallet', wallet);
this.wallet = JSON.parse(wallet);
}
}
Expand Down
12 changes: 10 additions & 2 deletions sample-app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@
<head>
<script src="linera.js"></script>
<script>
async function foo() {
async function makeQuery() {
const response = await Linera.sendRequest({
'function': 'query',
'arguments': [3],
});
console.log('response: ', response);
}

foo();

async function queryValidators() {
const response = await Linera.sendRequest({
'function': 'query_validators',
'arguments': [],
});
}
</script>
</head>
<body>
<button onclick="makeQuery()" type="button">Make a query</button>
<button onclick="queryValidators()" type="button">Query validators</button>
</body>
</html>

0 comments on commit 32504ab

Please sign in to comment.