Skip to content

Commit

Permalink
review changes and comments
Browse files Browse the repository at this point in the history
  • Loading branch information
turbocrime committed Jun 24, 2024
1 parent 85d685e commit 1133bcb
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 39 deletions.
34 changes: 24 additions & 10 deletions apps/extension/src/content-scripts/injected-connection-port.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
import { PraxMessage } from './message-event';
import { CRSessionClient } from '@penumbra-zone/transport-chrome/session-client';
import { PraxConnection } from '../message/prax';
import { PraxMessage } from './message-event';

// content script unconditionally announces itself to extension background.
void chrome.runtime.sendMessage(PraxConnection.Init);
// this script will init the page session upon instruction from an extension
// worker. init does not arrive in direct response to an emitted message, it is
// independent.

// listen for init command from background. this may arrive soon after announce,
// or much later, after a request is made. this activates the channel session
// that transports messages from the DOM channel into the Chrome runtime
// handler to listen for init command for this document
const initOnce = (
req: unknown,
// in a content script, sender is always an extension background script
_: chrome.runtime.MessageSender,
// content script message handlers are activated only by another
// script in the same extension using chrome.tabs.sendMessage
sender: chrome.runtime.MessageSender,
// this handler will only ever send an empty response
emptyResponse: (no?: never) => void,
) => {
if (req !== PraxConnection.Init) return false;
if (req !== PraxConnection.Init) {
// boolean return in handlers signals intent to respond
return false;
}

chrome.runtime.onMessage.removeListener(initOnce);

// create session, post port to window where the injected global can catch it
if (sender.id !== PRAX) {
throw new Error(`Unexpected sender ${sender.id}`);
}

// create session, post port to window where the injected global can catch it.
const port = CRSessionClient.init(PRAX);
window.postMessage({ [PRAX]: port } satisfies PraxMessage<MessagePort>, '/', [port]);

// handler is done
emptyResponse();

// boolean return in handlers signals intent to respond
return true;
};

// attach handler
chrome.runtime.onMessage.addListener(initOnce);

// announce
void chrome.runtime.sendMessage(PraxConnection.Init);
29 changes: 22 additions & 7 deletions apps/extension/src/listeners/message-prax-init.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
import { alreadyApprovedOrigin } from '../origins/approve-origin';
import { PraxConnection } from '../message/prax';
import { alreadyApprovedOrigin } from '../origins/approve-origin';
import { assertValidSender } from '../origins/valid-sender';

// trigger injected-connection-port when a known page inits.
// listen for page init
chrome.runtime.onMessage.addListener(
(req: unknown, sender, emptyResponse: (no?: never) => void) => {
if (req !== PraxConnection.Init) return false;
emptyResponse();
(
req,
unvalidatedSender,
// this handler will only ever send an empty response
emptyResponse: (no?: never) => void,
) => {
if (req !== PraxConnection.Init) {
// boolean return in handlers signals intent to respond
return false;
}

const validSender = assertValidSender(unvalidatedSender);

void (async () => {
const validSender = assertValidSender(sender);
const alreadyApproved = await alreadyApprovedOrigin(validSender.origin);
if (alreadyApproved)
if (alreadyApproved) {
void chrome.tabs.sendMessage(validSender.tab.id, PraxConnection.Init, {
// init only the specific document
frameId: validSender.frameId,
documentId: validSender.documentId,
});
}
})();

// handler is done
emptyResponse();

// boolean return in handlers signals intent to respond
return true;
},
);
43 changes: 29 additions & 14 deletions apps/extension/src/listeners/message-prax-request.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,48 @@
import { Code, ConnectError } from '@connectrpc/connect';
import { approveOrigin } from '../origins/approve-origin';
import { PraxConnection } from '../message/prax';
import { UserChoice } from '@penumbra-zone/types/user-choice';
import { PenumbraRequestFailure } from '@penumbra-zone/client';
import { UserChoice } from '@penumbra-zone/types/user-choice';
import { PraxConnection } from '../message/prax';
import { approveOrigin } from '../origins/approve-origin';
import { assertValidSender } from '../origins/valid-sender';

// listen for page connection requests.
// this is the only message we handle from an unapproved content script.
// listen for page requests for approval
chrome.runtime.onMessage.addListener(
(req, unvalidatedSender, respond: (failure?: PenumbraRequestFailure) => void) => {
if (req !== PraxConnection.Request) return false; // instruct chrome we will not respond
(
req,
unvalidatedSender,
// this handler responds with nothing, or an enumerated failure reason
respond: (failure?: PenumbraRequestFailure) => void,
) => {
if (req !== PraxConnection.Request) {
// boolean return in handlers signals intent to respond
return false;
}

const validSender = assertValidSender(unvalidatedSender);

void approveOrigin(validSender).then(
status => {
// user interacted with the popup, resulting in a choice.
// origin is already known, or popup choice was made
if (status === UserChoice.Approved) {
// the request was succesful
respond();
// init happens separately
// approval will trigger init (separate message, not a response)
void chrome.tabs.sendMessage(validSender.tab.id, PraxConnection.Init, {
// init only the specific document
frameId: validSender.frameId,
documentId: validSender.documentId,
});

// handler is done
respond();
} else {
// any other choice is a denial
respond(PenumbraRequestFailure.Denied);
}
},
e => {
// something is wrong. user may not have seen a popup.
if (globalThis.__DEV__) console.warn('Connection request listener failed:', e);
// something is wrong. user may not have seen a popup
if (globalThis.__DEV__) {
console.warn('Connection request listener failed:', e);
}

if (e instanceof ConnectError && e.code === Code.Unauthenticated) {
// the website should instruct the user to log in
Expand All @@ -42,6 +55,8 @@ chrome.runtime.onMessage.addListener(
}
},
);
return true; // instruct chrome to wait for the response

// boolean return in handlers signals intent to respond
return true;
},
);
8 changes: 0 additions & 8 deletions apps/extension/src/origins/valid-sender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,3 @@ export const assertValidSender = (sender?: chrome.runtime.MessageSender) => {

return sender as ValidSender;
};

export const isValidSender = (sender: chrome.runtime.MessageSender): sender is ValidSender => {
try {
return Boolean(assertValidSender(sender));
} catch {
return false;
}
};

0 comments on commit 1133bcb

Please sign in to comment.