Skip to content
Open
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
23 changes: 11 additions & 12 deletions src/firefox/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,18 +349,17 @@ export class FirefoxCore {
}
}

let serviceBuilder;
if (process.platform === 'win32') {
// On windows, firefox.ServiceBuilder() invoked from the MCP will hang.
// geckodriver has to be in the PATH. See Bug 2040849.
const geckodriverPath = await findGeckodriver();
logDebug(`Using geckodriver: ${geckodriverPath}`);
serviceBuilder = new firefox.ServiceBuilder(geckodriverPath);
} else {
// On other platforms, the default ServiceBuilder should locate and
// start geckodriver successfully.
serviceBuilder = new firefox.ServiceBuilder();
}
// Always resolve geckodriver ourselves rather than letting selenium-webdriver
// fall back to its bundled selenium-manager. The Linux selenium-manager
// shipped with selenium-webdriver 4.36.0 is an x86-64 binary, so on an
// aarch64 host it fails with "Exec format error" and the session dies with
// "Unable to obtain browser driver" even when a native geckodriver is in
// PATH. See Bug 2062055. On Windows the same call would hang instead
// (Bug 2040849). findGeckodriver() checks PATH, then the selenium cache,
// then downloads a platform-correct binary via the geckodriver package.
Comment on lines +352 to +359

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use a shorter comment

Suggested change
// Always resolve geckodriver ourselves rather than letting selenium-webdriver
// fall back to its bundled selenium-manager. The Linux selenium-manager
// shipped with selenium-webdriver 4.36.0 is an x86-64 binary, so on an
// aarch64 host it fails with "Exec format error" and the session dies with
// "Unable to obtain browser driver" even when a native geckodriver is in
// PATH. See Bug 2062055. On Windows the same call would hang instead
// (Bug 2040849). findGeckodriver() checks PATH, then the selenium cache,
// then downloads a platform-correct binary via the geckodriver package.
// Always resolve geckodriver ourselves rather than relying on selenium
// entirely. See Bug 2062055, 2040849.

const geckodriverPath = await findGeckodriver();
logDebug(`Using geckodriver: ${geckodriverPath}`);
const serviceBuilder = new firefox.ServiceBuilder(geckodriverPath);

if (this.logFilePath) {
// Open file for appending, create if doesn't exist
Expand Down
21 changes: 21 additions & 0 deletions tests/firefox/core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ describe('FirefoxCore connect() profile handling', () => {
const mockWindowSize = vi.fn();
const mockSetAcceptInsecureCerts = vi.fn();
const mockSetStdio = vi.fn();
const mockServiceBuilderCtor = vi.fn();

beforeEach(() => {
vi.clearAllMocks();
Expand All @@ -333,7 +334,11 @@ describe('FirefoxCore connect() profile handling', () => {
setAcceptInsecureCerts = mockSetAcceptInsecureCerts;
},
ServiceBuilder: class {
constructor(...args: unknown[]) {
mockServiceBuilderCtor(...args);
}
setStdio = mockSetStdio;
addArguments = vi.fn();
},
},
}));
Expand Down Expand Up @@ -383,4 +388,20 @@ describe('FirefoxCore connect() profile handling', () => {
join('/path/to/test/profile', MCP_PROFILE_DIR_NAME)
);
});

// Bug 2062055: with no geckodriver path, selenium-webdriver falls back to its
// bundled selenium-manager, whose Linux binary is x86-64 only — so on aarch64
// the session dies with "Unable to obtain browser driver" even when a native
// geckodriver is in PATH. Resolving the path ourselves avoids that entirely.
Comment on lines +392 to +395

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Bug 2062055: with no geckodriver path, selenium-webdriver falls back to its
// bundled selenium-manager, whose Linux binary is x86-64 only — so on aarch64
// the session dies with "Unable to obtain browser driver" even when a native
// geckodriver is in PATH. Resolving the path ourselves avoids that entirely.
// Bug 2062055: geckodriver path should always be resolved before
// calling the ServiceBuilder.

it('should build the geckodriver service with an explicit binary path', async () => {
const { FirefoxCore } = await import('@/firefox/core.js');

const core = new FirefoxCore({ headless: true });
await core.connect();

expect(mockServiceBuilderCtor).toHaveBeenCalledTimes(1);
const [geckodriverPath] = mockServiceBuilderCtor.mock.calls[0] as [unknown];
expect(typeof geckodriverPath).toBe('string');
expect(String(geckodriverPath)).toContain('geckodriver');
});
});