summaryrefslogtreecommitdiffstats
path: root/remote/test/puppeteer/packages/puppeteer-core/src/bidi/BrowserConnector.ts
diff options
context:
space:
mode:
Diffstat (limited to 'remote/test/puppeteer/packages/puppeteer-core/src/bidi/BrowserConnector.ts')
-rw-r--r--remote/test/puppeteer/packages/puppeteer-core/src/bidi/BrowserConnector.ts123
1 files changed, 123 insertions, 0 deletions
diff --git a/remote/test/puppeteer/packages/puppeteer-core/src/bidi/BrowserConnector.ts b/remote/test/puppeteer/packages/puppeteer-core/src/bidi/BrowserConnector.ts
new file mode 100644
index 0000000000..f616e90561
--- /dev/null
+++ b/remote/test/puppeteer/packages/puppeteer-core/src/bidi/BrowserConnector.ts
@@ -0,0 +1,123 @@
+/**
+ * @license
+ * Copyright 2023 Google Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import type {BrowserCloseCallback} from '../api/Browser.js';
+import {Connection} from '../cdp/Connection.js';
+import type {ConnectionTransport} from '../common/ConnectionTransport.js';
+import type {
+ BrowserConnectOptions,
+ ConnectOptions,
+} from '../common/ConnectOptions.js';
+import {ProtocolError, UnsupportedOperation} from '../common/Errors.js';
+import {debugError, DEFAULT_VIEWPORT} from '../common/util.js';
+
+import type {BidiBrowser} from './Browser.js';
+import type {BidiConnection} from './Connection.js';
+
+/**
+ * Users should never call this directly; it's called when calling `puppeteer.connect`
+ * with `protocol: 'webDriverBiDi'`. This method attaches Puppeteer to an existing browser
+ * instance. First it tries to connect to the browser using pure BiDi. If the protocol is
+ * not supported, connects to the browser using BiDi over CDP.
+ *
+ * @internal
+ */
+export async function _connectToBiDiBrowser(
+ connectionTransport: ConnectionTransport,
+ url: string,
+ options: BrowserConnectOptions & ConnectOptions
+): Promise<BidiBrowser> {
+ const {ignoreHTTPSErrors = false, defaultViewport = DEFAULT_VIEWPORT} =
+ options;
+
+ const {bidiConnection, closeCallback} = await getBiDiConnection(
+ connectionTransport,
+ url,
+ options
+ );
+ const BiDi = await import(/* webpackIgnore: true */ './bidi.js');
+ const bidiBrowser = await BiDi.BidiBrowser.create({
+ connection: bidiConnection,
+ closeCallback,
+ process: undefined,
+ defaultViewport: defaultViewport,
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
+ });
+ return bidiBrowser;
+}
+
+/**
+ * Returns a BiDiConnection established to the endpoint specified by the options and a
+ * callback closing the browser. Callback depends on whether the connection is pure BiDi
+ * or BiDi over CDP.
+ * The method tries to connect to the browser using pure BiDi protocol, and falls back
+ * to BiDi over CDP.
+ */
+async function getBiDiConnection(
+ connectionTransport: ConnectionTransport,
+ url: string,
+ options: BrowserConnectOptions
+): Promise<{
+ bidiConnection: BidiConnection;
+ closeCallback: BrowserCloseCallback;
+}> {
+ const BiDi = await import(/* webpackIgnore: true */ './bidi.js');
+ const {ignoreHTTPSErrors = false, slowMo = 0, protocolTimeout} = options;
+
+ // Try pure BiDi first.
+ const pureBidiConnection = new BiDi.BidiConnection(
+ url,
+ connectionTransport,
+ slowMo,
+ protocolTimeout
+ );
+ try {
+ const result = await pureBidiConnection.send('session.status', {});
+ if ('type' in result && result.type === 'success') {
+ // The `browserWSEndpoint` points to an endpoint supporting pure WebDriver BiDi.
+ return {
+ bidiConnection: pureBidiConnection,
+ closeCallback: async () => {
+ await pureBidiConnection.send('browser.close', {}).catch(debugError);
+ },
+ };
+ }
+ } catch (e) {
+ if (!(e instanceof ProtocolError)) {
+ // Unexpected exception not related to BiDi / CDP. Rethrow.
+ throw e;
+ }
+ }
+ // Unbind the connection to avoid memory leaks.
+ pureBidiConnection.unbind();
+
+ // Fall back to CDP over BiDi reusing the WS connection.
+ const cdpConnection = new Connection(
+ url,
+ connectionTransport,
+ slowMo,
+ protocolTimeout
+ );
+
+ const version = await cdpConnection.send('Browser.getVersion');
+ if (version.product.toLowerCase().includes('firefox')) {
+ throw new UnsupportedOperation(
+ 'Firefox is not supported in BiDi over CDP mode.'
+ );
+ }
+
+ // TODO: use other options too.
+ const bidiOverCdpConnection = await BiDi.connectBidiOverCdp(cdpConnection, {
+ acceptInsecureCerts: ignoreHTTPSErrors,
+ });
+ return {
+ bidiConnection: bidiOverCdpConnection,
+ closeCallback: async () => {
+ // In case of BiDi over CDP, we need to close browser via CDP.
+ await cdpConnection.send('Browser.close').catch(debugError);
+ },
+ };
+}