summaryrefslogtreecommitdiffstats
path: root/remote/test/puppeteer/src/common/BrowserConnector.ts
diff options
context:
space:
mode:
Diffstat (limited to 'remote/test/puppeteer/src/common/BrowserConnector.ts')
-rw-r--r--remote/test/puppeteer/src/common/BrowserConnector.ts159
1 files changed, 159 insertions, 0 deletions
diff --git a/remote/test/puppeteer/src/common/BrowserConnector.ts b/remote/test/puppeteer/src/common/BrowserConnector.ts
new file mode 100644
index 0000000000..8d65873c31
--- /dev/null
+++ b/remote/test/puppeteer/src/common/BrowserConnector.ts
@@ -0,0 +1,159 @@
+/**
+ * Copyright 2020 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {debugError} from './util.js';
+import {isErrorLike} from '../util/ErrorLike.js';
+import {isNode} from '../environment.js';
+import {assert} from '../util/assert.js';
+import {
+ Browser,
+ IsPageTargetCallback,
+ TargetFilterCallback,
+} from './Browser.js';
+import {Connection} from './Connection.js';
+import {ConnectionTransport} from './ConnectionTransport.js';
+import {getFetch} from './fetch.js';
+import {Viewport} from './PuppeteerViewport.js';
+/**
+ * Generic browser options that can be passed when launching any browser or when
+ * connecting to an existing browser instance.
+ * @public
+ */
+export interface BrowserConnectOptions {
+ /**
+ * Whether to ignore HTTPS errors during navigation.
+ * @defaultValue false
+ */
+ ignoreHTTPSErrors?: boolean;
+ /**
+ * Sets the viewport for each page.
+ */
+ defaultViewport?: Viewport | null;
+ /**
+ * Slows down Puppeteer operations by the specified amount of milliseconds to
+ * aid debugging.
+ */
+ slowMo?: number;
+ /**
+ * Callback to decide if Puppeteer should connect to a given target or not.
+ */
+ targetFilter?: TargetFilterCallback;
+ /**
+ * @internal
+ */
+ _isPageTarget?: IsPageTargetCallback;
+}
+
+const getWebSocketTransportClass = async () => {
+ return isNode
+ ? (await import('../node/NodeWebSocketTransport.js')).NodeWebSocketTransport
+ : (await import('./BrowserWebSocketTransport.js'))
+ .BrowserWebSocketTransport;
+};
+
+/**
+ * Users should never call this directly; it's called when calling
+ * `puppeteer.connect`.
+ *
+ * @internal
+ */
+export async function _connectToBrowser(
+ options: BrowserConnectOptions & {
+ browserWSEndpoint?: string;
+ browserURL?: string;
+ transport?: ConnectionTransport;
+ }
+): Promise<Browser> {
+ const {
+ browserWSEndpoint,
+ browserURL,
+ ignoreHTTPSErrors = false,
+ defaultViewport = {width: 800, height: 600},
+ transport,
+ slowMo = 0,
+ targetFilter,
+ _isPageTarget: isPageTarget,
+ } = options;
+
+ assert(
+ Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) ===
+ 1,
+ 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'
+ );
+
+ let connection!: Connection;
+ if (transport) {
+ connection = new Connection('', transport, slowMo);
+ } else if (browserWSEndpoint) {
+ const WebSocketClass = await getWebSocketTransportClass();
+ const connectionTransport: ConnectionTransport =
+ await WebSocketClass.create(browserWSEndpoint);
+ connection = new Connection(browserWSEndpoint, connectionTransport, slowMo);
+ } else if (browserURL) {
+ const connectionURL = await getWSEndpoint(browserURL);
+ const WebSocketClass = await getWebSocketTransportClass();
+ const connectionTransport: ConnectionTransport =
+ await WebSocketClass.create(connectionURL);
+ connection = new Connection(connectionURL, connectionTransport, slowMo);
+ }
+ const version = await connection.send('Browser.getVersion');
+
+ const product = version.product.toLowerCase().includes('firefox')
+ ? 'firefox'
+ : 'chrome';
+
+ const {browserContextIds} = await connection.send(
+ 'Target.getBrowserContexts'
+ );
+ const browser = await Browser._create(
+ product || 'chrome',
+ connection,
+ browserContextIds,
+ ignoreHTTPSErrors,
+ defaultViewport,
+ undefined,
+ () => {
+ return connection.send('Browser.close').catch(debugError);
+ },
+ targetFilter,
+ isPageTarget
+ );
+ await browser.pages();
+ return browser;
+}
+
+async function getWSEndpoint(browserURL: string): Promise<string> {
+ const endpointURL = new URL('/json/version', browserURL);
+
+ const fetch = await getFetch();
+ try {
+ const result = await fetch(endpointURL.toString(), {
+ method: 'GET',
+ });
+ if (!result.ok) {
+ throw new Error(`HTTP ${result.statusText}`);
+ }
+ const data = await result.json();
+ return data.webSocketDebuggerUrl;
+ } catch (error) {
+ if (isErrorLike(error)) {
+ error.message =
+ `Failed to fetch browser webSocket URL from ${endpointURL}: ` +
+ error.message;
+ }
+ throw error;
+ }
+}