// The approval window shows no screen until the background has described the // approval it answers (https://git.eeqj.de/sneak/AutistMask/issues/408). The // connection prompt's "Allow" and the network switch prompt's "Switch" answer // on the same port, so a window that showed the connection prompt while it // waited could approve a network switch. // // Booted through the real popup entry point, which is where the connection // prompt used to be put up before the background had answered. const { bootPopup, cleanupPopup, settle, unversionedValidProfile, } = require("./support/popupBoot"); afterEach(cleanupPopup); test("the approval window shows no screen until the background describes the approval", async () => { // The background's answer, held until the test gives it. let answer = null; const env = await bootPopup(unversionedValidProfile(), { search: "?approval=approval-1", runtime: { connect: () => ({ postMessage: () => {} }), sendMessage: (msg, reply) => { if (msg.type === "AUTISTMASK_GET_APPROVAL") answer = reply; }, }, }); expect(answer).not.toBeNull(); // No screen at all, the connection prompt included. expect(env.visibleViews()).toEqual([]); answer({ type: "network", origin: "https://dapp.example", currentNetworkId: "mainnet", requestedNetworkId: "sepolia", isPhishingDomain: false, }); await settle(); expect(env.visibleViews()).toEqual(["approve-network"]); expect(env.pageErrors).toEqual([]); }); // The background opens the approval window as wide as the page, but the // browser counts the window's frame in that width, and a screen taller than // the window takes a vertical scrollbar out of it too // (https://git.eeqj.de/sneak/AutistMask/issues/518). The browser suites run // without frames, and only the Firefox suite's sign prompt at a zoom other // than 100%, so the widening is checked here too. // // A window 396 screen pixels wide whose page is drawn at `drawn` screen pixels // to the page pixel. Widening it gives the page its new width, less the 15 // screen pixels of the scrollbar the approval screen has, and then calls the // page's resize listeners, each of which asked to be called once. function windowsStub(type, drawn) { const updates = []; return { updates, getCurrent: (done) => done({ id: 7, type, width: 396 }), update: (id, info, done) => { updates.push({ id, info }); done({}); globalThis.document.documentElement.clientWidth = Math.floor( (info.width - 15) / drawn, ); const resized = globalThis.window.listeners.resize || []; globalThis.window.listeners.resize = []; for (const fn of resized) fn(); }, }; } // The approval page's own tab is at `zoom`. Asked without a tab id, Firefox // answers for the window focused last, here a site's tab at 100%. function tabsStub(zoom) { return { getCurrent: (done) => done({ id: 11 }), getZoom: (...args) => { const done = args.pop(); done(args[0] === 11 ? zoom : 1); }, }; } // An approval window at `zoom`, `clientWidth` page pixels wide before its // screen is up, whose background holds its answer until the test gives it. async function bootZoomedApprovalWindow(windows, zoom, clientWidth) { let answer = null; const env = await bootPopup(unversionedValidProfile(), { search: "?approval=approval-1", runtime: { connect: () => ({ postMessage: () => {} }), sendMessage: (msg, reply) => { if (msg.type === "AUTISTMASK_GET_APPROVAL") answer = reply; }, }, windows, tabs: tabsStub(zoom), documentElement: { scrollWidth: 396, clientWidth }, }); return { env, answer }; } test("at 150% zoom the approval window widens by what its screen lacks, scrollbar included", async () => { const windows = windowsStub("popup", 1.5); // At 150% a window 396 screen pixels wide shows 264 page pixels. const { env, answer } = await bootZoomedApprovalWindow(windows, 1.5, 264); // Not before there is a screen to fit. expect(windows.updates).toEqual([]); // The screen is taller than the window, so once it is up a vertical // scrollbar takes 15 screen pixels, 10 page pixels at 150%. env.document.documentElement.clientWidth = 254; answer({ type: "network", origin: "https://dapp.example", currentNetworkId: "mainnet", requestedNetworkId: "sepolia", isPhishingDomain: false, }); await settle(); // 396 - 254 = 142 page pixels short, which at 150% is 213 screen pixels. // At the 100% of the site's tab it would be 142, and the screen would // still not fit. expect(env.visibleViews()).toEqual(["approve-network"]); expect(windows.updates).toEqual([{ id: 7, info: { width: 609 } }]); expect(env.document.documentElement.clientWidth).toBe(396); expect(env.pageErrors).toEqual([]); }); test("at 170% the approval window is widened again while its screen still falls short", async () => { // Firefox reports 170% as 1.7 but draws a page pixel about 1.714 screen // pixels wide, so a window 396 wide shows 231 page pixels. const windows = windowsStub("popup", 1.714); const { env, answer } = await bootZoomedApprovalWindow(windows, 1.7, 231); // Less the scrollbar once the screen is up. env.document.documentElement.clientWidth = 222; answer({ type: "network", origin: "https://dapp.example", currentNetworkId: "mainnet", requestedNetworkId: "sepolia", isPhishingDomain: false, }); await settle(); // 174 page pixels short, so 296 screen pixels wider at 1.7. That shows 394 // page pixels, still 2 short, so 4 screen pixels wider again. expect(windows.updates).toEqual([ { id: 7, info: { width: 692 } }, { id: 7, info: { width: 696 } }, ]); const page = env.document.documentElement; expect(page.scrollWidth).toBeLessThanOrEqual(page.clientWidth); expect(env.pageErrors).toEqual([]); }); test("a connection prompt in the toolbar popup leaves the browser window alone", async () => { const windows = windowsStub("normal", 1.5); const { env, answer } = await bootZoomedApprovalWindow(windows, 1.5, 264); answer({ origin: "https://dapp.example", isPhishingDomain: false }); await settle(); expect(env.visibleViews()).toEqual(["approve-site"]); expect(windows.updates).toEqual([]); expect(env.pageErrors).toEqual([]); });