Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/firefox/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Firefox uses Manifest V2 (background page, not service worker) and has **no access to the Chrome DevTools Protocol (CDP)**. Starting with v3.6.x, the Firefox build has been brought to functional parity with Chrome for the accessibility-tree (AX) subsystem — the same tree builder, the same four AX tools (`get_accessibility_tree`, `click_ax`, `type_ax`, `set_field`), and the same ref_id registry. What Firefox still lacks:

- **No trusted events** — clicks and key presses are synthetic (`el.click()`, `new KeyboardEvent()`), and some sites reject `event.isTrusted === false`. All AX-tool click/type paths use synthetic dispatch in Firefox; the CDP-backed trusted-event path in Chrome has no Firefox equivalent.
- **No pixel-perfect / full-page screenshots** — uses `browser.tabs.captureTab()` instead of CDP `Page.captureScreenshot`; it can capture the run tab while that tab is inactive. Firefox has exposed `tabs.captureTab()` since Firefox 59, before WebBrain's Firefox 109 minimum, and the manifest declares the required `<all_urls>` permission.
- **No pixel-perfect / full-page screenshots** — uses `browser.tabs.captureTab()` instead of CDP `Page.captureScreenshot`; it can capture the run tab while that tab is inactive. Firefox has exposed `tabs.captureTab()` since Firefox 59, before WebBrain's current minimum, and the manifest declares the required `<all_urls>` permission.
- **No shadow DOM piercing** — content script can read open shadow roots via `element.shadowRoot`, but cannot pierce closed roots.
- **No offscreen document** — no HTTP fetch proxy for localhost LLM servers with Private Network Access / CORS issues. User must ensure their local LLM server sends permissive CORS headers.
- **Some Chrome-only tools/features remain absent** — no CDP full-page screenshot, CDP upload automation, tab recording, offscreen fetch proxy, Chrome-only `shadow_dom_query`, or closed-shadow-root traversal.
Expand Down
2 changes: 1 addition & 1 deletion src/firefox/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
"browser_specific_settings": {
"gecko": {
"id": "webbrain@esokullu.com",
"strict_min_version": "109.0",
"strict_min_version": "140.0",
"data_collection_permissions": {
"required": ["none"],
"optional": ["personallyIdentifyingInfo", "authenticationInfo", "personalCommunications", "websiteContent", "technicalAndInteraction"]
Expand Down
2 changes: 1 addition & 1 deletion src/firefox/src/agent/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -6989,7 +6989,7 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
/**
* Capture a viewport screenshot for the run's tab without activating it.
* `tabs.captureTab()` has been available since Firefox 59; WebBrain's
* minimum is Firefox 109 and its `<all_urls>` permission authorizes capture.
* current minimum is newer, and its `<all_urls>` permission authorizes capture.
* Firefox supports `scale: 1` here to force a CSS-pixel-aligned image
* (otherwise it captures at devicePixelRatio, causing the same coordinate-
* mismatch loop Chrome had pre-1.5.1). Returns
Expand Down
22 changes: 22 additions & 0 deletions test/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -13492,6 +13492,28 @@ test('firefox manifest declares required data collection permissions for AMO', (
assert.deepEqual(manifest.browser_specific_settings?.gecko?.data_collection_permissions?.required, ['none']);
});

test('firefox minimum version covers declared manifest capabilities', () => {
const manifest = JSON.parse(fs.readFileSync(path.join(ROOT, 'src/firefox/manifest.json'), 'utf8'));
const declaredVersion = manifest.browser_specific_settings?.gecko?.strict_min_version;
const declaredVersionMatch = /^(\d+)(?:\.\d+)*$/.exec(declaredVersion);
const requirements = [];
if (manifest.permissions?.includes('tabGroups')) {
requirements.push({ feature: 'tabGroups permission', minimum: 139 });
}
if (manifest.browser_specific_settings?.gecko?.data_collection_permissions) {
requirements.push({ feature: 'data_collection_permissions', minimum: 140 });
}

assert.ok(declaredVersionMatch, 'Firefox strict_min_version must be a dotted numeric version');
const declaredMinimumMajor = Number(declaredVersionMatch[1]);
for (const requirement of requirements) {
assert.ok(
declaredMinimumMajor >= requirement.minimum,
`${requirement.feature} requires Firefox ${requirement.minimum}+, but strict_min_version is ${declaredVersion}`,
);
}
});

// ────────────────────────────────────────────────────────────────────────
// Context-aware recommended actions
// ────────────────────────────────────────────────────────────────────────
Expand Down