Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aedb729e02 |
@@ -3,6 +3,9 @@ on: [push]
|
|||||||
jobs:
|
jobs:
|
||||||
check:
|
check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# Bounds script/cibuild, a cold-cache build included, so a hang frees
|
||||||
|
# the shared runner. README.md "In CI" has the measured times.
|
||||||
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
# actions/checkout v4.2.2, 2026-02-22
|
# actions/checkout v4.2.2, 2026-02-22
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ on: [push]
|
|||||||
jobs:
|
jobs:
|
||||||
e2e-chrome:
|
e2e-chrome:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# Bounds the image build, a cold cache included, and both Chrome
|
||||||
|
# programs, so a hung browser frees the shared runner. README.md
|
||||||
|
# "In CI" has the measured times.
|
||||||
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
# actions/checkout v4.2.2, 2026-02-22
|
# actions/checkout v4.2.2, 2026-02-22
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
@@ -42,6 +46,10 @@ jobs:
|
|||||||
|
|
||||||
e2e-firefox:
|
e2e-firefox:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# Bounds the image build, a cold cache included, and both Firefox
|
||||||
|
# programs, so a hung browser frees the shared runner. README.md
|
||||||
|
# "In CI" has the measured times.
|
||||||
|
timeout-minutes: 15
|
||||||
steps:
|
steps:
|
||||||
# actions/checkout v4.2.2, 2026-02-22
|
# actions/checkout v4.2.2, 2026-02-22
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
|
|||||||
@@ -643,12 +643,20 @@ Nothing in either job can pass vacuously. There is no `continue-on-error` and no
|
|||||||
build fails, and when the browser fails to start; the Chrome harness aborts the
|
build fails, and when the browser fails to start; the Chrome harness aborts the
|
||||||
suite outright if its network interception is not in effect.
|
suite outright if its network interception is not in effect.
|
||||||
|
|
||||||
Measured on this repo's runner: `e2e-chrome` about 1m55s cold, almost all of it
|
Measured on this repo's runner in the green runs of early October 2026, from a
|
||||||
the one-time pull of the pinned ~800MB Playwright layer, and well under a minute
|
warm docker cache to a cold one: `check` 49s to 3m37s, `e2e-chrome` 1m44s to
|
||||||
once that layer is cached. `e2e-firefox` about 1m05s cold, and it caches its
|
4m48s, and `e2e-firefox` 31s to 4m07s. A cold cache adds three to four minutes
|
||||||
Firefox and geckodriver downloads the same way. The `e2e-chrome` figures predate
|
to each job, spent rebuilding its image: reinstalling dependencies and, for
|
||||||
the two cases that wait for a receipt to end in error, which add about two
|
`e2e-firefox`, installing Firefox, geckodriver and their system libraries. Those
|
||||||
minutes of real waiting.
|
`e2e-chrome` runs predate the cases that wait in real time for a receipt to end
|
||||||
|
in error. `make test-e2e` now takes 3m51s locally with its image cached, so a
|
||||||
|
cold `e2e-chrome` run comes to about seven minutes.
|
||||||
|
|
||||||
|
Every job has a `timeout-minutes` cap, so a hung build or browser ends the job
|
||||||
|
instead of holding the shared runner: `check` 10 minutes, `e2e-firefox` 15 and
|
||||||
|
`e2e-chrome` 20, each over two and a half times the job's slowest cold run. A
|
||||||
|
job that reaches its cap has hung; read it as a hang, not as a slow run to
|
||||||
|
retry.
|
||||||
|
|
||||||
### Element id guard (part of `make check`)
|
### Element id guard (part of `make check`)
|
||||||
|
|
||||||
|
|||||||
@@ -45,13 +45,11 @@ but the review is broader than any of them.
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
- 2026-10-05: `PROXY_METHODS` in `src/background/index.js` no longer lists
|
- 2026-10-05: Every CI job has a `timeout-minutes` cap
|
||||||
`eth_chainId` and `net_version`
|
([#294](https://git.eeqj.de/sneak/AutistMask/issues/294)): `check` 10 minutes,
|
||||||
([#326](https://git.eeqj.de/sneak/AutistMask/issues/326)). `handleRpc` answers
|
`e2e-firefox` 15 and `e2e-chrome` 20, each over two and a half times the job's
|
||||||
both itself before its proxy branch, so the list named two methods that are
|
slowest cold-cache run. A hung build or browser now ends its job instead of
|
||||||
never sent to the RPC endpoint. No other entry is answered earlier.
|
holding the shared runner for hours.
|
||||||
`tests/proxyMethods.test.js` sends every listed method from a page and fails
|
|
||||||
on any that does not reach the RPC endpoint.
|
|
||||||
|
|
||||||
- 2026-10-05: The popup's Content Security Policy no longer allows inline style
|
- 2026-10-05: The popup's Content Security Policy no longer allows inline style
|
||||||
([#328](https://git.eeqj.de/sneak/AutistMask/issues/328)): `style-src` is
|
([#328](https://git.eeqj.de/sneak/AutistMask/issues/328)): `style-src` is
|
||||||
|
|||||||
@@ -741,12 +741,11 @@ async function handleConnectionRequest(origin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods that are safe to proxy directly to the RPC node. A method handleRpc
|
// Methods that are safe to proxy directly to the RPC node
|
||||||
// answers before its proxy branch does not belong here: it would never reach
|
|
||||||
// the node. tests/proxyMethods.test.js sends every one of these.
|
|
||||||
const PROXY_METHODS = [
|
const PROXY_METHODS = [
|
||||||
"eth_blockNumber",
|
"eth_blockNumber",
|
||||||
"eth_call",
|
"eth_call",
|
||||||
|
"eth_chainId",
|
||||||
"eth_estimateGas",
|
"eth_estimateGas",
|
||||||
"eth_gasPrice",
|
"eth_gasPrice",
|
||||||
"eth_getBalance",
|
"eth_getBalance",
|
||||||
@@ -760,6 +759,7 @@ const PROXY_METHODS = [
|
|||||||
"eth_getTransactionReceipt",
|
"eth_getTransactionReceipt",
|
||||||
"eth_maxPriorityFeePerGas",
|
"eth_maxPriorityFeePerGas",
|
||||||
"eth_sendRawTransaction",
|
"eth_sendRawTransaction",
|
||||||
|
"net_version",
|
||||||
"web3_clientVersion",
|
"web3_clientVersion",
|
||||||
"eth_feeHistory",
|
"eth_feeHistory",
|
||||||
"eth_getBlockTransactionCountByHash",
|
"eth_getBlockTransactionCountByHash",
|
||||||
@@ -1802,5 +1802,3 @@ runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = { PROXY_METHODS };
|
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
// Every method in PROXY_METHODS is sent to the RPC node.
|
|
||||||
//
|
|
||||||
// handleRpc answers some methods itself before it reaches its proxy branch. A
|
|
||||||
// method listed in PROXY_METHODS but answered earlier never reaches the node,
|
|
||||||
// so the list would name a method that is not proxied
|
|
||||||
// (https://git.eeqj.de/sneak/AutistMask/issues/326). Each method is sent from
|
|
||||||
// a page here and must come back with what the node answered.
|
|
||||||
|
|
||||||
const { makeStorageStub } = require("./support/storageStub");
|
|
||||||
|
|
||||||
async function settle() {
|
|
||||||
for (let i = 0; i < 50; i++) await Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
delete global.chrome;
|
|
||||||
delete global.fetch;
|
|
||||||
});
|
|
||||||
|
|
||||||
test("every method in PROXY_METHODS reaches the RPC node", async () => {
|
|
||||||
jest.resetModules();
|
|
||||||
|
|
||||||
jest.doMock("../src/shared/balances", () => ({
|
|
||||||
getProvider: () => ({}),
|
|
||||||
refreshBalances: jest.fn(async () => {}),
|
|
||||||
}));
|
|
||||||
jest.doMock("../src/shared/phishingDomains", () => ({
|
|
||||||
isPhishingDomain: () => false,
|
|
||||||
}));
|
|
||||||
jest.doMock("../src/shared/alarms", () => ({
|
|
||||||
BALANCE_REFRESH_ALARM: "balance",
|
|
||||||
BALANCE_REFRESH_PERIOD_MINUTES: 1,
|
|
||||||
ensureRecurringAlarms: jest.fn(async () => {}),
|
|
||||||
registerAlarmHandlers: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// The node answers each method with a value naming that method.
|
|
||||||
global.fetch = jest.fn(async (url, opts) => ({
|
|
||||||
status: 200,
|
|
||||||
json: async () => ({
|
|
||||||
jsonrpc: "2.0",
|
|
||||||
id: 1,
|
|
||||||
result: "node answered " + JSON.parse(opts.body).method,
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
|
|
||||||
let messageListener = null;
|
|
||||||
global.chrome = {
|
|
||||||
storage: makeStorageStub({
|
|
||||||
autistmask: {
|
|
||||||
networkId: "mainnet",
|
|
||||||
wallets: [],
|
|
||||||
allowedSites: {},
|
|
||||||
deniedSites: {},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
runtime: {
|
|
||||||
getURL: (path) => "chrome-extension://autistmask/" + path,
|
|
||||||
onMessage: {
|
|
||||||
addListener: (fn) => {
|
|
||||||
messageListener = fn;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
onConnect: { addListener: () => {} },
|
|
||||||
lastError: null,
|
|
||||||
},
|
|
||||||
windows: { onRemoved: { addListener: () => {} } },
|
|
||||||
action: { setPopup: () => {} },
|
|
||||||
};
|
|
||||||
|
|
||||||
const { PROXY_METHODS } = require("../src/background/index");
|
|
||||||
|
|
||||||
const answers = {};
|
|
||||||
const expected = {};
|
|
||||||
for (const method of PROXY_METHODS) {
|
|
||||||
messageListener(
|
|
||||||
{ type: "AUTISTMASK_RPC", method, params: [] },
|
|
||||||
{ origin: "https://dapp.example" },
|
|
||||||
(r) => {
|
|
||||||
answers[method] = r;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
await settle();
|
|
||||||
expected[method] = { result: "node answered " + method };
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(PROXY_METHODS.length).toBeGreaterThan(0);
|
|
||||||
expect(answers).toEqual(expected);
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user