From 66f81d109739e9b6c81fa9b853661cc75562ae33 Mon Sep 17 00:00:00 2001 From: Step7750 Date: Fri, 7 Oct 2022 01:23:25 -0600 Subject: [PATCH 1/2] Adds an Example Handler --- src/lib/bridge/handlers/example.ts | 14 ++++++++++++++ src/lib/bridge/handlers/handlers.ts | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 src/lib/bridge/handlers/example.ts diff --git a/src/lib/bridge/handlers/example.ts b/src/lib/bridge/handlers/example.ts new file mode 100644 index 00000000..90de5b37 --- /dev/null +++ b/src/lib/bridge/handlers/example.ts @@ -0,0 +1,14 @@ +import {SimpleHandler} from './main'; +import {RequestType} from './handlers'; + +export interface ExampleRequest { + ping: string; +} + +export interface ExampleResponse { + pong: string; +} + +export const Example = new SimpleHandler(RequestType.EXAMPLE, async (req, sender) => { + return {pong: `${req.ping} reply!`}; +}); diff --git a/src/lib/bridge/handlers/handlers.ts b/src/lib/bridge/handlers/handlers.ts index a4358237..709310e3 100644 --- a/src/lib/bridge/handlers/handlers.ts +++ b/src/lib/bridge/handlers/handlers.ts @@ -9,8 +9,10 @@ import {RequestHandler} from '../types'; import {FetchPendingTrades} from './fetch_pending_trades'; import {FetchSkinModel} from './fetch_skin_model'; import {StorageRemove} from './storage_remove'; +import {Example} from './example'; export enum RequestType { + EXAMPLE, EXECUTE_SCRIPT_ON_PAGE, EXECUTE_CSS_ON_PAGE, FETCH_INSPECT_INFO, @@ -24,6 +26,7 @@ export enum RequestType { } export const HANDLERS_MAP: {[key in RequestType]: RequestHandler} = { + [RequestType.EXAMPLE]: Example, [RequestType.EXECUTE_SCRIPT_ON_PAGE]: ExecuteScriptOnPage, [RequestType.EXECUTE_CSS_ON_PAGE]: ExecuteCssOnPage, [RequestType.FETCH_INSPECT_INFO]: FetchInspectInfo, From efcd314c26747f5acf3f2f0653078e8b19ad855a Mon Sep 17 00:00:00 2001 From: Step7750 Date: Fri, 7 Oct 2022 01:23:45 -0600 Subject: [PATCH 2/2] Creates Docs Related to the Bridge --- src/lib/bridge/README.md | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/lib/bridge/README.md diff --git a/src/lib/bridge/README.md b/src/lib/bridge/README.md new file mode 100644 index 00000000..be1d2f4a --- /dev/null +++ b/src/lib/bridge/README.md @@ -0,0 +1,69 @@ +# Bridge + +The bridge provides a type-safe abstraction layer for communication between +the page/content script and background script. + +## Why? + +* The page/content script cannot access certain Chrome extension APIs +* The page/content script cannot execute AJAX requests to domains outside of Steam's CSP policy + +## How? + +The bridge operates similar to a client/server request/response model. You can think of it +as sending requests to an HTTP server with type-safe handling. + +The [`background.ts`](../background.ts) script runs a "server" handler that attempts to find +the appropriate handler for a given message, executes it, then returns the result. + +If the handler fails to execute for any reason, the promise in the client will throw with the reason. + +## Restricting Access + +By default, bridge methods can be called by any Steam page's JavaScript and the extension content script. + +Some methods may be considered too _sensitive_ to expose to the page and can be wrapped as a +`Privileged` handler. This restricts it to only be called from the extension's content script -- ensuring that +only audited CSGOFloat code can access. + +Notably, executing scripts and CSS on the relevant Steam page is protected by this. + +Example: + +```javascript +export const MyPrivilegedHandler = new PrivilegedHandler( + new EmptyResponseHandler(RequestType.MY_PRIVILEGED_HANDLER, async (req, sender) => { + return {}; + }) +); +``` + +## Using a Handler + +### Send a Message + +```javascript +import {ClientSend} from '../client'; + +const result = await ClientSend(FetchInspectInfo, {inspectLink: "steam://rungame/...D11702291663056892105"}); +``` + +This is all type-safe, so any IDE will help you fill in the arguments needed for that handler type. + +## Creating a Handler + +> **Note** +> You should only create a handler if it needs to access an HTTP resource outside of Steam CSP or Chrome extension API + +1) Add your new request type to the `RequestType` enum in [`handlers.ts`](handlers/handlers.ts) +2) Create a `.ts` file in [`handlers/`](handlers/) for your new handler + * The file name should generally match the enum (ex. `FETCH_INSPECT_INFO` -> `fetch_inspect_info.ts`) +3) Create a default implementation for your handler + * See [`example.ts`](handlers/example.ts) for inspiration + * Decide whether to use `SimpleHandler`, `EmptyRequestHandler`, `EmptyResponseHandler` depending on your use-case +4) Does your handler access potentially sensitive resources? Wrap it in `PrivilegedHandler` + * See [`execute_script.ts`](handlers/execute_script.ts) for an example +5) Add mapping from the `RequestType` enum to your handler in [`handlers.ts`](handlers/handlers.ts) +6) You should be good to go to start using your handler! + * Note that if you're running `npm start` with the development extension open in Chrome, you'll need to **reload** + the extension in `chrome://extensions/` to update the service worker.