|
5 | 5 | import { WebDriver } from 'selenium-webdriver'; |
6 | 6 | import { log, logDebug } from '../utils/logger.js'; |
7 | 7 |
|
8 | | -const PRIVILEGED_URL_SCHEMES = ['moz-extension:']; |
| 8 | +const COMMON_URL_SCHEMES = ['http:', 'https:', 'data:', 'blob:', 'file:']; |
9 | 9 |
|
10 | 10 | /** |
11 | | - * Check if a URL uses a privileged scheme that requires BiDi navigation. |
12 | | - * @internal Exported for testability only; not a stable public API. |
| 11 | + * Check if a URL uses a common scheme that supports load events. |
| 12 | + * Non-common schemes = moz-extension:, about:, ... |
13 | 13 | */ |
14 | | -export function isPrivilegedUrl(url: string): boolean { |
| 14 | +export function isCommonScheme(url: string): boolean { |
15 | 15 | try { |
16 | | - return PRIVILEGED_URL_SCHEMES.includes(new URL(url).protocol); |
| 16 | + return COMMON_URL_SCHEMES.includes(new URL(url).protocol); |
17 | 17 | } catch { |
18 | | - logDebug(`URL parse failed, treating as non-privileged: ${url}`); |
19 | 18 | return false; |
20 | 19 | } |
21 | 20 | } |
22 | 21 |
|
| 22 | +export type BiDiCommandFn = (method: string, params: Record<string, any>) => Promise<any>; |
| 23 | + |
23 | 24 | export class PageManagement { |
24 | 25 | constructor( |
25 | 26 | private driver: WebDriver, |
26 | 27 | private getCurrentContextId: () => string | null, |
27 | 28 | private setCurrentContextId: (id: string) => void, |
28 | | - private sendBiDiCommand?: (method: string, params: Record<string, any>) => Promise<any> |
| 29 | + private sendBiDiCommand: BiDiCommandFn |
29 | 30 | ) {} |
30 | 31 |
|
31 | 32 | /** |
32 | | - * Navigate to URL. |
33 | | - * For moz-extension:// URLs, uses BiDi browsingContext.navigate with |
34 | | - * wait:"none" because geckodriver |
35 | | - * waits for BiDi navigation completion events that the Remote Agent does |
36 | | - * not emit for extension/privileged contexts, causing driver.get() to hang. |
| 33 | + * Navigate to URL using BiDi |
37 | 34 | */ |
38 | 35 | async navigate(url: string): Promise<void> { |
39 | | - if (isPrivilegedUrl(url) && this.sendBiDiCommand) { |
40 | | - const contextId = this.getCurrentContextId(); |
41 | | - if (!contextId) { |
42 | | - throw new Error(`Cannot navigate to privileged URL ${url}: no browsing context ID`); |
43 | | - } |
44 | | - await this.sendBiDiCommand('browsingContext.navigate', { |
45 | | - context: contextId, |
46 | | - url, |
47 | | - wait: 'none', |
48 | | - }); |
49 | | - logDebug(`BiDi navigate (wait:none) to: ${url}`); |
50 | | - } else { |
51 | | - await this.driver.get(url); |
| 36 | + const contextId = this.getCurrentContextId(); |
| 37 | + if (!contextId) { |
| 38 | + throw new Error(`Cannot navigate: no browsing context ID`); |
52 | 39 | } |
| 40 | + |
| 41 | + // Default wait time is "interactive" (DOMContentLoaded). |
| 42 | + // All uncommon schemes use wait time "none" |
| 43 | + const wait = isCommonScheme(url) ? 'interactive' : 'none'; |
| 44 | + |
| 45 | + // Navigate using direct BiDi |
| 46 | + await this.sendBiDiCommand('browsingContext.navigate', { |
| 47 | + context: contextId, |
| 48 | + url, |
| 49 | + wait, |
| 50 | + }); |
| 51 | + |
| 52 | + logDebug(`BiDi navigate (wait:${wait}) to: ${url}`); |
53 | 53 | log(`Navigated to: ${url}`); |
54 | 54 | } |
55 | 55 |
|
|
0 commit comments